Repository: icebob/fastest-validator
Pull request #57 (2019-02-05 13:39:49)

Add feature to allow personalised error messages per field.
I've added tests and updated the readme if you are happy to include this feature.


Patch:
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..b2026e5
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,30 @@
+# EditorConfig helps developers define and maintain consistent
+# coding styles between different editors and IDEs
+# editorconfig.org
+
+root = true
+
+[*]
+
+# Change these settings to your own preference
+indent_style = tab
+indent_size = 4
+space_after_anon_function = true
+
+# We recommend you to keep these unchanged
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
+indent_style = space
+indent_size = 4
+
+[{package,bower}.json]
+indent_style = space
+indent_size = 2
+
+[*.js]
+quote_type = "double"
diff --git a/README.md b/README.md
index b6b49f5..1a6ab6c 100644
--- a/README.md
+++ b/README.md
@@ -48,7 +48,7 @@ You can install it via [NPM](http://npmjs.org/).
 ```
 $ npm install fastest-validator --save
 ```
-or 
+or
 ```
 $ yarn add fastest-validator
 ```
@@ -56,7 +56,7 @@ $ yarn add fastest-validator
 ## Usage
 
 ### Simple method
-Call the `validate` method with the `object` and the `schema`. 
+Call the `validate` method with the `object` and the `schema`.
 > If performance is important, you won't use this method.
 
 ```js
@@ -76,7 +76,7 @@ console.log(v.validate({ id: 5, name: "John", status: true }, schema));
 console.log(v.validate({ id: 5, name: "Al", status: true }, schema));
 /* Returns an array with errors:
     [
-        { 
+        {
             type: 'stringMin',
             expected: 3,
             actual: 2,
@@ -111,7 +111,7 @@ console.log(check({ id: 5, name: "John", status: true }));
 console.log(check({ id: 2, name: "Adam" }));
 /* Returns an array with errors:
     [
-        { 
+        {
             type: 'required',
             field: 'status',
             message: 'The \'status\' field is required!'
@@ -187,7 +187,7 @@ v.validate({ prop: "John" }, schema); // Valid
 ```
 
 ## `array`
-This is an `Array` validator. 
+This is an `Array` validator.
 
 **Simple example with strings:**
 ```js
@@ -226,7 +226,7 @@ let schema = {
     } }
 }
 
-v.validate({ 
+v.validate({
     users: [
         { id: 1, name: "John", status: true },
         { id: 2, name: "Jane", status: true },
@@ -259,7 +259,7 @@ v.validate({ roles: ["guest"] }, schema); // Fail
 
 
 ## `boolean`
-This is a `Boolean` validator. 
+This is a `Boolean` validator.
 
 ```js
 let schema = {
@@ -278,7 +278,7 @@ Property | Default  | Description
 
 
 ## `date`
-This is a `Date` validator. 
+This is a `Date` validator.
 
 ```js
 let schema = {
@@ -295,7 +295,7 @@ Property | Default  | Description
 `convert`  | `false`| if `true` and the type is not `Date`, try to convert with `new Date()`.
 
 ## `email`
-This is an e-mail address validator. 
+This is an e-mail address validator.
 
 ```js
 let schema = {
@@ -313,7 +313,7 @@ Property | Default  | Description
 `mode`   | `quick`  | Checker method. Can be `quick` or `precise`.
 
 ## `enum`
-This is an enum validator. 
+This is an enum validator.
 
 ```js
 let schema = {
@@ -332,7 +332,7 @@ Property | Default  | Description
 
 
 ## `forbidden`
-This validator returns an error if the property exists in the object. 
+This validator returns an error if the property exists in the object.
 
 ```js
 let schema = {
@@ -393,15 +393,15 @@ let schema = {
     } }
 }
 
-v.validate({ 
+v.validate({
     address: {
         country: "Italy",
         city: "Rome",
         zip: 12345
-    } 
+    }
 }, schema); // Valid
 
-v.validate({ 
+v.validate({
     address: {
         country: "Italy",
         city: "Rome"
@@ -440,7 +440,7 @@ Property | Default  | Description
 
 
 ## `url`
-This is an URL validator. 
+This is an URL validator.
 
 ```js
 let schema = {
@@ -502,9 +502,9 @@ let v = new Validator({
 
 const schema = {
 	name: { type: "string", min: 3, max: 255 },
-	weight: { 
-		type: "custom", 
-		minWeight: 10, 
+	weight: {
+		type: "custom",
+		minWeight: 10,
 		check(value, schema) {
 			return (value < schema.minWeight)
 				? this.makeError("weightMin", schema.minWeight, value)
@@ -518,12 +518,12 @@ console.log(v.validate({ name: "John", weight: 50 }, schema));
 
 console.log(v.validate({ name: "John", weight: 8 }, schema));
 /* Returns an array with errors:
-	[{ 
-		type: 'weightMin',                                       
-		expected: 10,                                            
-		actual: 8,                                               
-		field: 'weight',                                         
-		message: 'The weight must be greater than 10! Actual: 8' 
+	[{
+		type: 'weightMin',
+		expected: 10,
+		actual: 8,
+		field: 'weight',
+		message: 'The weight must be greater than 10! Actual: 8'
 	}]
 */
 ```
@@ -542,18 +542,61 @@ const v = new Validator({
 
 v.validate({ name: "John" }, { name: { type: "string", min: 6 }});
 /* Returns:
-[ 
-    { 
+[
+    {
         type: 'stringMin',
         expected: 6,
         actual: 4,
         field: 'name',
-        message: 'A(z) \'name\' mező túl rövid. Minimum: 6, Jelenleg: 4' 
-    } 
+        message: 'A(z) \'name\' mező túl rövid. Minimum: 6, Jelenleg: 4'
+    }
 ]
 */
 ```
+# Personalised Messages
+Sometimes the standard messages are too generic. You can customise messages per validation type per field:
 
+```js
+const Validator = require("fastest-validator");
+const v = new Validator();
+const schema = {
+    firstname: {
+        type: "string",
+        min: 6,
+        messages: {
+            string: "Please check your firstname",
+            stringMin: "Your firstname is too short"
+        }
+    },
+    lastname: {
+        type: "string",
+        min: 6,
+        messages: {
+            string: "Please check your lastname",
+            stringMin: "Your lastname is too short"
+        }
+    }
+}
+v.validate({ firstname: "John", lastname: 23 }, schema );
+/* Returns:
+[
+    {
+        type: 'stringMin',
+        expected: 6,
+        actual: 4,
+        field: 'firstname',
+        message: 'Your firstname is too short'
+    },
+    {
+        type: 'string',
+        expected: undefined,
+        actual: undefined,
+        field: 'lastname',
+        message: 'Please check your lastname'
+    }
+]
+*/
+```
 ## Message types
 Name                | Default text
 ------------------- | -------------
diff --git a/benchmark/suites/simple.js b/benchmark/suites/simple.js
index a6482af..04ff9fe 100644
--- a/benchmark/suites/simple.js
+++ b/benchmark/suites/simple.js
@@ -32,7 +32,27 @@ const schema = {
 	},
 	email: { type: "email" },
 	firstName: { type: "string" },
-	phone: { type: "string" },
+	phone: { type: "string"},
+	age: {
+		type: "number",
+		min: 18
+	}
+};
+
+const schema2 = {
+	name: {
+		type: "string",
+		min: 4,
+		max: 25,
+		messages: {
+			string: "Csak szöveges érték",
+			stringMin: "Túl rövid!",
+			stringMax: "Túl hosszú"
+		}
+	},
+	email: { type: "email" },
+	firstName: { type: "string" },
+	phone: { type: "string"},
 	age: {
 		type: "number",
 		min: 18
@@ -40,22 +60,27 @@ const schema = {
 };
 
 bench.ref("compile & validate", () => {
-	let res = v.validate(obj, schema);		
+	const res = v.validate(obj, schema);
 	if (res !== true)
 		throw new Error("Validation error!", res);
 });
 
+bench.add("compile & validate with custom messages", () => {
+	const res = v.validate(obj, schema2);
+	if (res !== true)
+		throw new Error("Validation error!", res);
+});
 
-let check = v.compile(schema);
+const check = v.compile(schema);
 
 bench.add("validate with pre-compiled schema", () => {
-	let res = check(obj);
+	const res = check(obj);
 	if (res !== true)
 		throw new Error("Validation error!", res);
 });
 
 bench.add("validate with wrong obj", () => {
-	let res = check(wrongObj);
+	const res = check(wrongObj);
 	if (res === true)
 		throw new Error("Validation error!", res);
 });
@@ -86,4 +111,4 @@ Suite: Simple object
    validate with wrong obj                 -36.79%        (704,992 rps)   (avg: 1μs)
 -----------------------------------------------------------------------
 
-*/
\ No newline at end of file
+*/
diff --git a/lib/rules/email.js b/lib/rules/email.js
index 3345d41..b207104 100644
--- a/lib/rules/email.js
+++ b/lib/rules/email.js
@@ -1,6 +1,6 @@
 "use strict";
 
-const PRECISE_PATTERN = /^(([^<>()[\]\\.,;:\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,}))$/;
+const PRECISE_PATTERN = /^(([^<>()[\]\\.,;:\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,}))$/;
 const BASIC_PATTERN = /^\S+@\S+\.\S+$/;
 
 module.exports = function checkEmail(value, schema) {
@@ -13,7 +13,7 @@ module.exports = function checkEmail(value, schema) {
 		pattern = PRECISE_PATTERN;
 	else
 		pattern = BASIC_PATTERN;
-	
+
 	if (!pattern.test(value)) {
 		return this.makeError("email");
 	}
diff --git a/lib/rules/string.js b/lib/rules/string.js
index 2f3b5b2..ee275f5 100644
--- a/lib/rules/string.js
+++ b/lib/rules/string.js
@@ -3,7 +3,7 @@
 const NUMERIC_PATTERN = /^-?[0-9]\d*(\.\d+)?$/;
 const ALPHA_PATTERN = /^[a-zA-Z]+$/;
 const ALPHANUM_PATTERN = /^[a-zA-Z0-9]+$/;
-const ALPHADASH_PATTERN = /^[a-zA-Z0-9_\-]+$/;
+const ALPHADASH_PATTERN = /^[a-zA-Z0-9_-]+$/;
 
 module.exports = function checkString(value, schema) {
 	if (typeof value !== "string") {
@@ -26,7 +26,7 @@ module.exports = function checkString(value, schema) {
 
 	if (schema.length != null && valueLength !== schema.length) {
 		return this.makeError("stringLength", schema.length, valueLength);
-	}	
+	}
 
 	if (schema.pattern != null) {
 		const pattern = typeof schema.pattern == "string" ? new RegExp(schema.pattern, schema.patternFlags) : schema.pattern;
@@ -36,7 +36,7 @@ module.exports = function checkString(value, schema) {
 
 	if (schema.contains != null && value.indexOf(schema.contains) === -1) {
 		return this.makeError("stringContains", schema.contains);
-	}	
+	}
 
 	if (schema.enum != null && schema.enum.indexOf(value) === -1) {
 		return this.makeError("stringEnum", schema.enum);
@@ -59,4 +59,4 @@ module.exports = function checkString(value, schema) {
 	}
 
 	return true;
-};
\ No newline at end of file
+};
diff --git a/lib/validator.js b/lib/validator.js
index cc7d5a8..f1809f8 100644
--- a/lib/validator.js
+++ b/lib/validator.js
@@ -31,7 +31,7 @@ const escapeEvalRegex = /["'\\\n\r\u2028\u2029]/g;
 
 function escapeEvalString(str) {
 	// Based on https://github.com/joliss/js-string-escape
-	return str.replace(escapeEvalRegex, function (character) {
+	return str.replace(escapeEvalRegex, function(character) {
 		switch (character) {
 		case "\"":
 		case "'":
@@ -64,6 +64,7 @@ function Validator(opts) {
 		deepExtend(this.opts, opts);
 
 	this.messages = this.opts.messages;
+	this.messageKeys = Object.keys(this.messages);
 
 	// Load rules
 	this.rules = loadRules();
@@ -90,7 +91,7 @@ Validator.prototype.validate = function(obj, schema) {
 Validator.prototype.compile = function(schema) {
 	const self = this;
 	if (Array.isArray(schema)) {
-		// Multiple schemas
+	// Multiple schemas
 		if (schema.length == 0) {
 			throw new Error("If the schema is an Array, must contain at least one element!");
 		}
@@ -100,7 +101,7 @@ Validator.prototype.compile = function(schema) {
 		return function(value, path, parent) {
 			return self.checkSchemaType(value, rules, path, parent || null);
 		};
-	} 
+	}
 
 	const rule = this.compileSchemaObject(schema);
 	this.cache.clear();
@@ -118,14 +119,14 @@ Validator.prototype.compileSchemaObject = function(schemaObject) {
 	if (compiledObject) {
 		compiledObject.cycle = true;
 		return compiledObject;
-	} else{
+	} else {
 		compiledObject = { cycle: false, properties: null, compiledObjectFunction: null, objectStack: [] };
 		this.cache.set(schemaObject, compiledObject);
 	}
 
 	compiledObject.properties = Object.keys(schemaObject).map(name => {
 		const compiledType = this.compileSchemaType(schemaObject[name]);
-		return {name: name, compiledType: compiledType};
+		return { name: name, compiledType: compiledType };
 	});
 
 	const sourceCode = [];
@@ -144,7 +145,7 @@ Validator.prototype.compileSchemaObject = function(schemaObject) {
 			sourceCode.push(`res = this.checkSchemaRule(${propertyValueExpr}, properties[${i}].compiledType, propertyPath, value);`);
 		}
 		sourceCode.push("if (res !== true) {");
-		sourceCode.push("\tthis.handleResult(errors, propertyPath, res);");
+		sourceCode.push(`\tthis.handleResult(errors, propertyPath, res, properties[${i}].compiledType.messages);`);
 		sourceCode.push("}");
 	}
 
@@ -156,9 +157,12 @@ Validator.prototype.compileSchemaObject = function(schemaObject) {
 };
 
 Validator.prototype.compileSchemaType = function(schemaType) {
+
 	if (Array.isArray(schemaType)) {
+
 		// Multiple rules, flatten to array of compiled SchemaRule
 		const rules = flatten(schemaType.map(r => this.compileSchemaType(r)));
+
 		if (rules.length == 1) {
 			return rules[0];
 		}
@@ -167,9 +171,23 @@ Validator.prototype.compileSchemaType = function(schemaType) {
 	}
 
 	return this.compileSchemaRule(schemaType);
+
+};
+
+Validator.prototype.compileMessages = function(schemaType) {
+
+	if (schemaType.messages) {
+		return this.messageKeys.reduce((a, key) => {
+			a[key] = schemaType.messages[key] || this.messages[key];
+			return a;
+		}, {});
+	}
+
+	return this.messages;
 };
 
 Validator.prototype.compileSchemaRule = function(schemaRule) {
+
 	if (typeof schemaRule === "string") {
 		schemaRule = {
 			type: schemaRule
@@ -177,10 +195,13 @@ Validator.prototype.compileSchemaRule = function(schemaRule) {
 	}
 
 	const ruleFunction = this.rules[schemaRule.type];
+
 	if (!ruleFunction) {
 		throw new Error("Invalid '" + schemaRule.type + "' type in validator schema!");
 	}
 
+	const messages = this.compileMessages(schemaRule);
+
 	let dataParameter = null;
 	let dataFunction = null;
 
@@ -193,6 +214,7 @@ Validator.prototype.compileSchemaRule = function(schemaRule) {
 	}
 
 	return {
+		messages: messages,
 		schemaRule: schemaRule,
 		ruleFunction: ruleFunction,
 		dataFunction: dataFunction,
@@ -219,26 +241,28 @@ Validator.prototype.checkSchemaObjectInner = function(value, compiledObject, pat
 	return compiledObject.compiledObjectFunction.call(this, value, compiledObject.properties, path, parent);
 
 	/*
-	// Reference implementation of the object checker
-
-	const errors = [];
-	const propertiesLength = compiledObject.properties.length;
-	for (let i = 0; i < propertiesLength; i++) {
-		const property = compiledObject.properties[i];
-		const propertyPath = (path !== undefined ? path + "." : "") + property.name;
-		const res = this.checkSchemaType(value[property.name], property.compiledType, propertyPath, value);
-
-		if (res !== true) {
-			this.handleResult(errors, propertyPath, res);
-		}
-	}
-
-	return errors.length === 0 ? true : errors;
-	*/
+    // Reference implementation of the object checker
+
+    const errors = [];
+    const propertiesLength = compiledObject.properties.length;
+    for (let i = 0; i < propertiesLength; i++) {
+    const property = compiledObject.properties[i];
+    const propertyPath = (path !== undefined ? path + "." : "") + property.name;
+    const res = this.checkSchemaType(value[property.name], property.compiledType, propertyPath, value);
+
+    if (res !== true) {
+    this.handleResult(errors, propertyPath, res);
+    }
+    }
+
+    return errors.length === 0 ? true : errors;
+    */
 };
 
 Validator.prototype.checkSchemaType = function(value, compiledType, path, parent) {
+
 	if (Array.isArray(compiledType)) {
+
 		const errors = [];
 		const checksLength = compiledType.length;
 		for (let i = 0; i < checksLength; i++) {
@@ -246,7 +270,7 @@ Validator.prototype.checkSchemaType = function(value, compiledType, path, parent
 			const res = this.checkSchemaRule(value, compiledType[i], path, parent);
 
 			if (res !== true) {
-				this.handleResult(errors, path, res);
+				this.handleResult(errors, path, res, compiledType.messages);
 			} else {
 				// Jump out after first success and clear previous errors
 				return true;
@@ -254,7 +278,7 @@ Validator.prototype.checkSchemaType = function(value, compiledType, path, parent
 		}
 
 		return errors;
-	} 
+	}
 
 	return this.checkSchemaRule(value, compiledType, path, parent);
 };
@@ -268,7 +292,7 @@ Validator.prototype.checkSchemaArray = function(value, compiledArray, path, pare
 		const res = this.checkSchemaType(value[i], compiledArray, itemPath, value, parent);
 
 		if (res !== true) {
-			this.handleResult(errors, itemPath, res);
+			this.handleResult(errors, itemPath, res, compiledArray.messages);
 		}
 	}
 
@@ -286,14 +310,17 @@ Validator.prototype.checkSchemaRule = function(value, compiledRule, path, parent
 			return true;
 
 		const errors = [];
-		this.handleResult(errors, path, this.makeError("required"));
+		this.handleResult(errors, path, this.makeError("required"), compiledRule.messages);
+
 		return errors;
 	}
 
 	const res = compiledRule.ruleFunction.call(this, value, schemaRule, path, parent);
+
 	if (res !== true) {
 		const errors = [];
-		this.handleResult(errors, path, res);
+		this.handleResult(errors, path, res, compiledRule.messages);
+
 		return errors;
 	}
 
@@ -311,7 +338,7 @@ Validator.prototype.checkSchemaRule = function(value, compiledRule, path, parent
  * @param {String} fieldPath
  * @param {Array|Object} res
  */
-Validator.prototype.handleResult = function(errors, fieldPath, res) {
+Validator.prototype.handleResult = function(errors, fieldPath, res, messages) {
 	let items;
 	if (!Array.isArray(res))
 		items = [res];
@@ -322,7 +349,7 @@ Validator.prototype.handleResult = function(errors, fieldPath, res) {
 		if (!err.field)
 			err.field = fieldPath;
 		if (!err.message)
-			err.message = this.resolveMessage(err);
+			err.message = this.resolveMessage(err, messages[err.type]);
 
 		errors.push(err);
 	});
@@ -348,8 +375,8 @@ Validator.prototype.makeError = function(type, expected, actual) {
  *
  * @param {Object} err Validation error object
  */
-Validator.prototype.resolveMessage = function(err) {
-	let msg = this.messages[err.type];
+Validator.prototype.resolveMessage = function(err, msg = null) {
+
 	if (msg != null) {
 		const expected = err.expected != null ? err.expected : "";
 		const actual = err.actual != null ? err.actual : "";
diff --git a/package.json b/package.json
index 6a2e32f..cf378dc 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,8 @@
     "dev": "nodemon examples/index.js",
     "ci": "jest --watch",
     "test": "jest --coverage",
-    "lint": "eslint --ext=.js src test rollup.config.js",
+    "lint": "eslint --ext=.js lib test rollup.config.js",
+    "lint:fix": "eslint --fix --ext=.js lib test rollup.config.js",
     "deps": "npm-check -u",
     "coverall": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js"
   },


Test patch:
diff --git a/test/rules/custom_messages.spec.js b/test/rules/custom_messages.spec.js
new file mode 100644
index 0000000..8af661b
--- /dev/null
+++ b/test/rules/custom_messages.spec.js
@@ -0,0 +1,101 @@
+"use strict";
+
+const Validator = require("../../lib/validator");
+const v = new Validator();
+
+describe("Test custom messages", () => {
+
+	it("should give back not a string message", () => {
+
+		const message = "That wasn't a string!";
+		const s = { name: { type: "string", messages: { string: message } } };
+
+		expect(v.validate({ name: 123 }, s)).toEqual([{ type: "string", expected: undefined, actual: undefined, field: "name", message }]);
+
+	});
+
+	it("should give back required message", () => {
+
+		const message = "Your name is required!";
+
+		const s = { name: { type: "string", messages: { required: message } } };
+
+		expect(v.validate({}, s)).toEqual([{ type: "required", expected: undefined, actual: undefined, field: "name", message: message }]);
+
+	});
+
+	it("should do replacements in custom messages", () => {
+
+		const message = "Incorrect name length. Your field: {field} had {actual} chars when it should have no more than {expected}";
+		const s = { name: { type: "string", max: 2, messages: { stringMax: message } } };
+
+		expect(v.validate({ name: "Long string" }, s)).toEqual([{ type: "stringMax", expected: 2, actual: 11, field: "name", message: "Incorrect name length. Your field: name had 11 chars when it should have no more than 2" }]);
+
+	});
+
+	it("should do custom messages in arrays", () => {
+
+		const s = {
+			cache: [
+				{ type: "string", messages: { string: "Not a string" } },
+				{ type: "boolean", messages: { boolean: "Not a boolean" } }
+			]
+		};
+
+		expect(v.validate({ cache: 123 }, s)).toEqual([{ type: "string", field: "cache", message: "Not a string" }, { type: "boolean", field: "cache", message: "Not a boolean" }]);
+
+	});
+
+	it("should do custom messages in objects", () => {
+
+		const s = {
+			users: {
+				type: "array",
+				items: {
+					type: "object",
+					props: {
+						id: { type: "number", positive: true, messages: { "number": "numbers only please" } },
+						name: { type: "string", empty: false, messages: { "string": "make sure it's a string" } },
+						status: "boolean"
+					}
+				}
+			}
+		};
+
+		expect(v.validate({
+			users: [
+				{ id: "test", name: "John", status: true },
+				{ id: 2, name: 123, status: true },
+				{ id: 3, name: "Bill", status: false }
+			]
+		}, s)).toEqual([{ type: "number", field: "users[0].id", message: "numbers only please" }, { type: "string", field: "users[1].name", message: "make sure it's a string" }]);
+
+	});
+
+	it("should do custom messages when compiled", () => {
+		const s = {
+			users: {
+				type: "array",
+				items: {
+					type: "object",
+					props: {
+						id: { type: "number", positive: true, messages: { "number": "numbers only please" } },
+						name: { type: "string", empty: false, messages: { "string": "make sure it's a string" } },
+						status: "boolean"
+					}
+				}
+			}
+		};
+
+		const check = v.compile(s);
+
+		expect(check({
+			users: [
+				{ id: "test", name: "John", status: true },
+				{ id: 2, name: 123, status: true },
+				{ id: 3, name: "Bill", status: false }
+			]
+		})).toEqual([{ type: "number", field: "users[0].id", message: "numbers only please" }, { type: "string", field: "users[1].name", message: "make sure it's a string" }]);
+
+	});
+});
diff --git a/test/validator.spec.js b/test/validator.spec.js
index 195ccae..7d0a515 100644
--- a/test/validator.spec.js
+++ b/test/validator.spec.js
@@ -110,18 +110,18 @@ describe("Test resolveMessage", () => {
 	const v = new Validator();
 
 	it("should resolve variables in message string", () => {
-		let res = v.resolveMessage({ type: "stringLength", field: "age", expected: 3, actual: 6 });
+		let res = v.resolveMessage({ type: "stringLength", field: "age", expected: 3, actual: 6 }, v.messages["stringLength"] );
 		expect(res).toBe("The 'age' field length must be 3 characters long!");
 	});
 
 	it("should resolve 0 value in message string", () => {
-		let res = v.resolveMessage({ type: "numberNotEqual", field: "b", expected: 0, actual: 0 });
+		let res = v.resolveMessage({ type: "numberNotEqual", field: "b", expected: 0, actual: 0 }, v.messages["numberNotEqual"] );
 		expect(res).toBe("The 'b' field can't be equal with 0!");
 	});
 
 	it("should resolve more variables in message string", () => {
 		v.messages.custom = "Field {field} and again {field}. Expected: {expected}, actual: {actual}.";
-		let res = v.resolveMessage({ type: "custom", field: "country", expected: "London", actual: 350 });
+		let res = v.resolveMessage({ type: "custom", field: "country", expected: "London", actual: 350 },  v.messages.custom );
 		expect(res).toBe("Field country and again country. Expected: London, actual: 350.");
 	});
 
@@ -354,7 +354,7 @@ describe("Test compile (integration test)", () => {
 
 		it("when schema is defined as an object, and custom path is specified, it should be forwarded to validators", () => {
 			// Note: as the item we validate always must be an object, there is no use
-			// of specifying a custom parent, like for the schema-as-array above. 
+			// of specifying a custom parent, like for the schema-as-array above.
 			// The parent is currently used in the validator code (only forwarded to the generated
 			// function that validates all properties) and there is no way to test it.
 			const v = new Validator();
@@ -687,19 +687,19 @@ describe("Test multiple rules with objects", () => {
 
 	let schema = {
 		list: [
-			{ 
+			{
 				type: "object",
 				props: {
 					name: {type: "string"},
 					age: {type: "number"},
-				} 
+				}
 			},
-			{ 
+			{
 				type: "object",
 				props: {
 					country: {type: "string"},
 					code: {type: "string"},
-				} 
+				}
 			}
 		]
 	};
@@ -768,19 +768,19 @@ describe("Test multiple rules with objects within array", () => {
 		list: {
 			type: "array",
 			items: [
-				{ 
+				{
 					type: "object",
 					props: {
 						name: {type: "string"},
 						age: {type: "number"},
-					} 
+					}
 				},
-				{ 
+				{
 					type: "object",
 					props: {
 						country: {type: "string"},
 						code: {type: "string"},
-					} 
+					}
 				}
 			]
 		}
@@ -907,9 +907,9 @@ describe("Test multiple rules with mixed types", () => {
 		expect(res).toBeInstanceOf(Array);
 		expect(res.length).toBe(2);
 		expect(res[0].type).toBe("string");
-		expect(res[0].field).toBe("value");		
+		expect(res[0].field).toBe("value");
 		expect(res[1].type).toBe("boolean");
-		expect(res[1].field).toBe("value");		
+		expect(res[1].field).toBe("value");
 	});
 
 	it("should give error if 'undefined'", () => {
@@ -919,9 +919,9 @@ describe("Test multiple rules with mixed types", () => {
 		expect(res).toBeInstanceOf(Array);
 		expect(res.length).toBe(2);
 		expect(res[0].type).toBe("required");
-		expect(res[0].field).toBe("value");		
+		expect(res[0].field).toBe("value");
 		expect(res[1].type).toBe("required");
-		expect(res[1].field).toBe("value");		
+		expect(res[1].field).toBe("value");
 	});
 
 });
@@ -931,13 +931,13 @@ describe("Test multiple rules with arrays", () => {
 
 	let schema = {
 		list: [
-			{ 
+			{
 				type: "array",
-				items: "string" 
+				items: "string"
 			},
-			{ 
+			{
 				type: "array",
-				items: "number" 
+				items: "number"
 			}
 		]
 	};
@@ -994,13 +994,13 @@ describe("Test multiple array in root", () => {
 	const v = new Validator();
 
 	let schema = [
-		{ 
+		{
 			type: "array",
-			items: "string" 
+			items: "string"
 		},
-		{ 
+		{
 			type: "array",
-			items: "number" 
+			items: "number"
 		}
 	];