Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Custom (user-friendly) ValidatorError message #753

Closed
wants to merge 17 commits into from
@ManInTheBox

Related to #747

Validators now accepts custom error message or if not provided, built-in error message will be used.
Error messages are borrowed from Yii PHP Framework and are stored in errormessages.json.

var UserSchema = new Schema({
  name: {
    first: {
      type: String,
      required: [ true, 'Field {path} is required.' ]
    },
    last: {
      type: String,
      max: [ 30, '{path|Your dear last name} is limited to {max} characters.' ]
    }
  },
  age: {
    type: Number,
    max: 100,
    min: [ 5, 'Minimum value for {path|Your age} is {min}.' ]
  }
});

This will be translated as:

  • Field Name First is required
  • Your dear last name is limited to 30 characters.
  • Age is too big (maximum is 100).
  • Minimum value for Your age is 5.

Also, CastError is improved with built-in cast error message like:
Age must be a number.

I added three new String validators, min, max and length, because I think these are common.

@chanced

Thanks!

@katsgeorgeek

+1 Thanks

@aheckmann
Owner

why use 'Minimum value for {path|Your age} is {min}.' and not Minimum value for your age is {min}?

i'd prefer to keep the new string validators out of mongoose and instead have those available as a plugin.

can you add tests for these changes including cast error tests? then merge with latest master please.

thanks!

@ManInTheBox

Actually there's no need for {path|Your label}. Ofc it will work as you mentioned above... I realized that right after sending pull request :D It will be removed.

Sure, I'll add tests soon.

Cheers

@aheckmann
Owner

great!

@kof
kof commented

@ManInTheBox what do you think about #887 ?

@ManInTheBox

@kof ValidatorError.toString() and CastError.toString() will output user-friendly messages (see below):

{ message: 'Validation failed',
  name: 'ValidationError',
  errors: 
   { 'name.username': 
      { message: 'Username cannot be blank.',
        name: 'ValidatorError',
        path: 'name.username',
        type: 'required' },
     email: 
      { message: 'E-mail cannot be blank.',
        name: 'ValidatorError',
        path: 'email',
        type: 'required' },
     password: 
      { message: 'Password cannot be blank.',
        name: 'ValidatorError',
        path: 'password',
        type: 'required' } } }

For CastError there's a slightly different format (it stops on first cast error, so there's no errors object):

{ message: 'Test must be a valid date.',
  name: 'CastError',
  type: 'date',
  value: 'asdf' }

If you need to find out what caused an error you can check err.name -> name: "ValidationError".

if (err) {
  if (err.name === 'ValidationError') {
    // display validation errors to user
  } else if (err.name === 'CastError') {
    // display cast error message to user
  } else {
    // something related to db happened... crap!
  }
}

If you want to display nice error summary box, just iterate through err.errors object:

// eg jade
  - if (user.errors)
    div(class='error')
      ul
        - each err in user.errors
          li= err // <-- ValidatorError.toString()

real example:
https://github.com/ManInTheBox/nodejs.rs/blob/master/routes/user.js#L47
https://github.com/ManInTheBox/nodejs.rs/blob/master/views/user/register.jade#L5

I think this will fit your needs.

btw @aheckmann I've stuck for a while with MongooseArray. Concrete with this test. Can't get path of embedded document. It's always 'undefined', though arr expected.
In a couple of next days, I hope I will push back added tests. I'm just too busy with another project right now.

@kof
kof commented

I am still missing the value of the field in the error, this is what I expect to find in logs:

{ message: 'Validation failed',
  name: 'ValidationError',
  errors: 
   { email: 
      { message: 'E-mail is not valide.',
        name: 'ValidatorError',
        path: 'email',
        type: 'required',
        value: '123234r@web.c' },
     password: 
      { message: 'Password cannot be blank.',
        name: 'ValidatorError',
        path: 'password',
        type: 'required' } } }

In this example if you don't get the email string, you will not be able to understand why is the issue happened. An email regex will not say it to you.

@ManInTheBox

Yup, you're right!
I'll include value key in ValidatorError and also path key in CastError.
Your thoughts?

@kof
kof commented

fine, the second thing is ValidatorError.prototype.toString method. It should return all error informations, not just the message, for me it is fine if you just use util.format so the result will look like in your example in previous comment (formatted json). The reason is to make it convinent (no need to log errors array separately) and consistent relative to other error handlings:

doc.save(function(err) { 
    if (err) {
        return next(new Error(err));
    }
})

Error constructor will point in stack trace to this code and will call #toString method so get the stringified version of ValidationError. I believe this is the way how the most user handle errors in node.

@kof
kof commented

I am not sure if the stringified version of error should/can be mulitiline formatted. Probably "ValidationError: Validation failed. {email:{message:'E-mailisnotvalide.',name:'ValidatorError',path:'email',type:'required',value:'123234r@web.c'},password:{message:'Passwordcannotbeblank.',name:'ValidatorError',path:'password',type:'required'}}}" is fine.

@kof
kof commented

probably something like this

ValidatorError.prototype.toString = function() {
    return this.name + ': ' + this.message + ' ' + JSON.stringify(this.errors);   
};
@ManInTheBox

@kof what's the difference between this:

if (err) return next(err);

and this:

if (err) return next(new Error(err));

???

err is an instance of Error object so there's no need to instantiate another one...

I'm using first approach in Express and it's error handler catches that just fine.

If you want to print err object its #toString() is called, and it's reasonable (at least for me) to output its message. If you need detailed information about error object (e.g. for logging purposes), you have that whole error object.

Let's hear what others think about this.

Cheers

@kof
kof commented

You need detailed information about the error if the error is happened. If it is happend and logged message is not complete you need to add detailed information in code and wait until the error happens again. This process is messy, everyone want to get the whole description at the moment error is happened.

One could log .errors array in one central place, but there is this new Error(err) thingy, which will only pass the stringified version of the error. Sometimes one can pass just the original err, but very often you want to know which function has got the error instance.

@kof
kof commented

of course one could call everywere captureStackTrace instead of new Error(), then pass just the original error instance, so the endpoint logger can check for err.errors and log them all, but this is not handy.

if (err) {
    Error.captureStackTrace(err);
    return next(err);
}
@aheckmann
Owner

@kof are you saying you want error objects to record where they were logged?

@kof
kof commented

@aheckmann yes, but this is not because I want to know where they are logged, but to know in which callback they were passed, to see which function has called the function which has passed to my callback the error object.

need example?

@kof
kof commented

The point is we need both:
1. information about were does the error happend
2. how does it comes to happen

The 1. one is surely the original Error instance, but you haven't the 2. one if you don't add call points to stack. Actually it is a misuse of Error constructor in this case, because we actually don't want to create a new error, we just want to add a stack to this point, but it is handy and it wokred for all errors which return complete information from #toString.

@kof
kof commented

Thoughts?

@kof
kof commented

I have played with captureStackTrace method now, and found out, that it adds ALL function call pointers

function log(err) {
    Error.captureStackTrace(err);
    console.error(err.stack);
}

function test1(err) {
    log(err);
}

function test2(err) {
    test1(err);
}

function run() {
    //test1(new Error('test1'));
    test2(new Error('test2'));
}

run();

Error: test2
at log (/Users/kof/work/projects/test.js:9:11)
at test1 (/Users/kof/work/projects/test.js:14:5)
at test2 (/Users/kof/work/projects/test.js:18:5)
at run (/Users/kof/work/projects/test.js:23:5)
at Object. (/Users/kof/work/projects/test.js:26:1)
at Module._compile (module.js:441:26)
at Object..js (module.js:459:10)
at Module.load (module.js:348:31)
at Function._load (module.js:308:12)
at Array.0 (module.js:479:10)

So both my points can be solved just by calling ´Error.captureStackTrace(err);` in the end function, which is logging.

So please ignore my concerns about #toString method implementation.

Thanks!

@kof
kof commented

So the endpoint logger can just check if (err.errors) log(JSON.stringify(err.errors))

@kof

Anyone at home? :)

@kof
kof commented

Do I understand correctly, the reason why this pull isn't merged is missing tests? @ManInTheBox do you want to add them?

@ManInTheBox

Yes, that's the reason and I'm planning to add them.
I really apologize for really long delay, but I was just too busy with many ongoing projects (jobs). One of them is Serbian Node.js community website nodejs.rs which is very important to me. I hope next week I will add tests and complete this pull request :)

@kof
kof commented

@ManInTheBox thanks, really waiting for this one :)

@aheckmann
Owner

sounds good. i was planning on revisiting this pull and a few others after 3.0 stable is out.

@ManInTheBox

@aheckmann congrats to v3 release!
this pull will require a little more adjustments according to v3 (it's really old code now :) ) so please be patient... think it will be available in next few days... thanks!

@aheckmann
Owner

just merged locally but there were a ton of failing tests. this looks pretty good but we need all tests to pass and be backwards compatible before we can merge it in.

@ManInTheBox

@aheckmann yeah, i will provide all passing tests (don't have spare time right now). please try/review now b/c i fixed existing tests broken by this feature. also i will write better docs according to this pull. i have few failing test and IMO they aren't related to this pull:
https://gist.github.com/3794045
https://gist.github.com/3794030

@kof

I just had the case, where knowing the query which was send to mongo would save a lot of time. Can we add it to the err object? (conditions, options, new values)

This could be also the same string like one we get if mongoose.set('debug', true)

@ecdeveloper

Hi all, guys!

Just wanted to ask - when can we wait for this pull request being merged to master? I'd like to use this awesome feature of User-Friendly errors stuff, without checking out some non-master branches.

Thanks in advance!

@ManInTheBox

Hi,
it's not ready for master yet since some tests still missing. I'm planning to add them in about ~10 days. Out of time ATM :S
Thanks!

@ecdeveloper

Thanks for a quick reply!
Will wait for release :)

@dexcell

No update news?
I think it's pretty crucial, right now i have to manually check and return error messages accordingly. (which make double job / redundant since it's already defined in the schema)

@richzw

+1

This is we needed.

@rogovdm

We need this very much.

@vizo

+1

@aheckmann aheckmann closed this
@vizo

Can i ask what is the status of this?

@daslicht

I would also like to know this please

@blakehaswell blakehaswell referenced this pull request in blakehaswell/mongoose-unique-validator
Closed

Customizing Error Message ? #1

@daslicht

Such kind of feature should be built in

@cherta cherta referenced this pull request in jsconfuy/site-2014
Closed

Change the validation errors #4

@otang

+1

@tjworks

+1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 22, 2012
  1. @ManInTheBox
Commits on Feb 23, 2012
  1. @ManInTheBox
Commits on Feb 24, 2012
  1. @ManInTheBox

    completed error constructors, normalizeMessage support, added min, ma…

    ManInTheBox authored
    …x and length string validators
  2. @ManInTheBox

    string max typo fix

    ManInTheBox authored
  3. @ManInTheBox
  4. @ManInTheBox

    String match support

    ManInTheBox authored
  5. @ManInTheBox

    String enum support

    ManInTheBox authored
  6. @ManInTheBox

    Date cast error message

    ManInTheBox authored
Commits on Feb 27, 2012
  1. @ManInTheBox

    completed

    ManInTheBox authored
Commits on Feb 28, 2012
  1. @ManInTheBox
  2. @ManInTheBox
Commits on Aug 8, 2012
  1. @ManInTheBox

    great beta merge

    ManInTheBox authored
Commits on Sep 16, 2012
  1. @ManInTheBox
Commits on Sep 17, 2012
  1. @ManInTheBox
Commits on Sep 27, 2012
  1. @ManInTheBox
  2. @ManInTheBox

    Merge branch 'mongoose'

    ManInTheBox authored
  3. @ManInTheBox
This page is out of date. Refresh to see the latest.
View
29 lib/errors/cast.js
@@ -2,26 +2,49 @@
* Module dependencies.
*/
-var MongooseError = require('../error');
+var MongooseError = require('../error')
+ , errorMessages = require('./messages')
+ , utils = require('../utils')
+ ;
/**
* Casting Error constructor.
*
* @param {String} type
* @param {String} value
+ * @param {String} message
+ * @param {String} path
* @inherits MongooseError
* @api private
*/
-function CastError (type, value) {
- MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '"');
+function CastError (type, value, message, path) {
+
+ if ('undefined' === typeof message) { // if still don't have message
+ message = 'Cast to ' + type + ' failed for value "' + value + '"';
+ }
+
+ if ('undefined' === typeof path) {
+ path = type
+ }
+
+ MongooseError.call(this, utils.normalizeMessage(path, message));
Error.captureStackTrace(this, arguments.callee);
this.name = 'CastError';
this.type = type;
+ this.path = path;
this.value = value;
};
/*!
+ * toString helper
+ */
+
+CastError.prototype.toString = function () {
+ return this.message;
+}
+
+/*!
* Inherits from MongooseError.
*/
View
16 lib/errors/messages.json
@@ -0,0 +1,16 @@
+{
+ "required": "{path} cannot be blank."
+ , "string": {
+ "match": "{path} is invalid."
+ , "enum": "{path} is not in the list."
+ , "cast": "{path} must be a string."
+ }
+ , "number": {
+ "min": "{path} is too small (minimum is {min})."
+ , "max": "{path} is too big (maximum is {max})."
+ , "cast": "{path} must be a number."
+ }
+ , "date": {
+ "cast": "{path} must be a valid date."
+ }
+}
View
28 lib/errors/validator.js
@@ -2,26 +2,38 @@
* Module dependencies.
*/
-var MongooseError = require('../error');
+var MongooseError = require('../error')
+ , errorMessages = require('./messages')
+ , utils = require('../utils')
+ ;
/**
* Schema validator error
*
* @param {String} path
- * @param {String} msg
+ * @param {String} type
+ * @param {String} message
+ * @param {Any} value
* @inherits MongooseError
* @api private
*/
-function ValidatorError (path, type) {
- var msg = type
- ? '"' + type + '" '
- : '';
- MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
+function ValidatorError (path, type, message, value) {
+ message = message || errorMessages[type];
+
+ if ('undefined' === typeof message) { // if still don't have message
+ var msg = type
+ ? '"' + type + '" '
+ : '';
+ message = 'Validator ' + msg + 'failed for path ' + path;
+ }
+
+ MongooseError.call(this, utils.normalizeMessage(path, message));
Error.captureStackTrace(this, arguments.callee);
this.name = 'ValidatorError';
- this.path = path;
this.type = type;
+ this.path = path;
+ this.value = value;
};
/*!
View
6 lib/schema/date.js
@@ -4,7 +4,8 @@
*/
var SchemaType = require('../schematype')
- , CastError = SchemaType.CastError;
+ , CastError = SchemaType.CastError
+ , errorMessages = require('../errors/messages');
/**
* Date SchemaType constructor.
@@ -63,7 +64,8 @@ SchemaDate.prototype.cast = function (value) {
if (date.toString() != 'Invalid Date')
return date;
- throw new CastError('date', value);
+ var message = errorMessages['date']['cast'];
+ throw new CastError('date', value, message, this.path);
};
/*!
View
26 lib/schema/number.js
@@ -4,6 +4,7 @@
var SchemaType = require('../schematype')
, CastError = SchemaType.CastError
+ , errorMessages = require('../errors/messages');
/**
* Number SchemaType constructor.
@@ -39,7 +40,7 @@ SchemaNumber.prototype.checkRequired = function checkRequired (value) {
};
/**
- * Sets a maximum number validator.
+ * Sets a minimum number validator
*
* ####Example:
*
@@ -53,7 +54,7 @@ SchemaNumber.prototype.checkRequired = function checkRequired (value) {
* })
*
* @param {Number} value minimum number
- * @param {String} message
+ * @param {String} optional error message
* @api public
*/
@@ -62,10 +63,13 @@ SchemaNumber.prototype.min = function (value, message) {
this.validators = this.validators.filter(function(v){
return v[1] != 'min';
});
- if (value != null)
- this.validators.push([function(v){
+ if (value != null) {
+ message = message || errorMessages['number']['min'];
+ message = message.replace('{min}', value);
+ this.validators.push([this.minValidator = function(v){
return v === null || v >= value;
- }, 'min']);
+ }, 'min', message]);
+ }
return this;
};
@@ -84,7 +88,7 @@ SchemaNumber.prototype.min = function (value, message) {
* })
*
* @param {Number} maximum number
- * @param {String} message
+ * @param {String} optional error message
* @api public
*/
@@ -93,10 +97,13 @@ SchemaNumber.prototype.max = function (value, message) {
this.validators = this.validators.filter(function(v){
return v[1] != 'max';
});
- if (value != null)
+ if (value != null) {
+ message = message || errorMessages['number']['max'];
+ message = message.replace('{max}', value);
this.validators.push([this.maxValidator = function(v){
return v === null || v <= value;
- }, 'max']);
+ }, 'max', message]);
+ }
return this;
};
@@ -124,7 +131,8 @@ SchemaNumber.prototype.cast = function (value, doc, init) {
}
}
- throw new CastError('number', value);
+ var message = errorMessages['number']['cast'];
+ throw new CastError('number', value, message, this.path);
};
/*!
View
23 lib/schema/string.js
@@ -4,7 +4,8 @@
*/
var SchemaType = require('../schematype')
- , CastError = SchemaType.CastError;
+ , CastError = SchemaType.CastError
+ , errorMessages = require('../errors/messages');
/**
* String SchemaType constructor.
@@ -58,6 +59,14 @@ SchemaString.prototype.enum = function () {
return;
}
+ var message = null;
+ // we have custom error message passed
+ if (arguments[0] instanceof Array) {
+ len = arguments[0].length;
+ message = arguments[1];
+ arguments = arguments[0];
+ }
+
for (var i = 0; i < len; i++) {
if (undefined !== arguments[i]) {
this.enumValues.push(this.cast(arguments[i]));
@@ -69,7 +78,8 @@ SchemaString.prototype.enum = function () {
this.enumValidator = function(v){
return undefined === v || ~values.indexOf(v);
};
- this.validators.push([this.enumValidator, 'enum']);
+ message = message || errorMessages['string']['enum'];
+ this.validators.push([this.enumValidator, 'enum', message]);
}
};
@@ -153,15 +163,17 @@ SchemaString.prototype.trim = function () {
* })
*
* @param {RegExp} regExp regular expression to test against
+ * @param {String} optional error message
* @api public
*/
-SchemaString.prototype.match = function match (regExp) {
+SchemaString.prototype.match = function match (regExp, message) {
+ message = message || errorMessages['string']['match'];
this.validators.push([function(v){
return null != v && '' !== v
? regExp.test(v)
: true
- }, 'regexp']);
+ }, 'regexp', message]);
};
/**
@@ -189,7 +201,8 @@ SchemaString.prototype.cast = function (value, scope, init) {
if (SchemaType._isRef(this, value, init)) return value;
if (value === null) return value;
if ('undefined' !== typeof value && value.toString) return value.toString();
- throw new CastError('string', value);
+ var message = errorMessages['string']['cast'];
+ throw new CastError('string', value, message, this.path);
};
/*!
View
35 lib/schematype.js
@@ -3,7 +3,8 @@
*/
var utils = require('./utils');
-var CastError = require('./errors/cast')
+var errorMessages = require('./errors/messages');
+var CastError = require('./errors/cast');
var ValidatorError = require('./errors/validator')
/**
@@ -320,12 +321,12 @@ SchemaType.prototype.get = function (fn) {
*
* function validator () { ... }
*
- * var single = [validator, 'failed']
+ * var single = [validator, 'validator type', 'failed']
* new Schema({ name: { type: String, validate: single }});
*
* var many = [
- * { validator: validator, msg: 'uh oh' }
- * , { validator: fn, msg: 'failed' }
+ * { validator: validator, type: 'validator1 type', msg: 'uh oh' }
+ * , { validator: fn, type: 'validator2 type', msg: 'failed' }
* ]
* new Schema({ name: { type: String, validate: many }});
*
@@ -362,13 +363,14 @@ SchemaType.prototype.get = function (fn) {
* Product.on('error', handleError);
*
* @param {RegExp|Function|Object} obj validator
+ * @param {String} type
* @param {String} [error] optional error message
* @api public
*/
-SchemaType.prototype.validate = function (obj, error) {
+SchemaType.prototype.validate = function (obj, type, error) {
if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
- this.validators.push([obj, error]);
+ this.validators.push([obj, type, error]);
return this;
}
@@ -384,7 +386,7 @@ SchemaType.prototype.validate = function (obj, error) {
throw new Error(msg);
}
- this.validate(arg.validator, arg.msg);
+ this.validate(arg.validator, arg.type, arg.msg);
}
return this;
@@ -401,11 +403,12 @@ SchemaType.prototype.validate = function (obj, error) {
*
*
* @param {Boolean} required enable/disable the validator
+ * @param {String} optional error message
* @return {SchemaType} this
* @api public
*/
-SchemaType.prototype.required = function (required) {
+SchemaType.prototype.required = function (required, message) {
var self = this;
function __checkRequired (v) {
@@ -424,7 +427,8 @@ SchemaType.prototype.required = function (required) {
});
} else {
this.isRequired = true;
- this.validators.push([__checkRequired, 'required']);
+ message = message || errorMessages['required'];
+ this.validators.push([__checkRequired, 'required', message]);
}
return this;
@@ -547,28 +551,29 @@ SchemaType.prototype.doValidate = function (value, fn, scope) {
if (!count) return fn(null);
- function validate (val, msg) {
+ function validate (val, type, msg) {
if (err) return;
if (val === undefined || val) {
--count || fn(null);
} else {
- fn(err = new ValidatorError(path, msg));
+ fn(err = new ValidatorError(path, type, msg, value));
}
}
this.validators.forEach(function (v) {
var validator = v[0]
- , message = v[1];
+ , type = v[1]
+ , message = v[2];
if (validator instanceof RegExp) {
- validate(validator.test(value), message);
+ validate(validator.test(value), type, message);
} else if ('function' === typeof validator) {
if (2 === validator.length) {
validator.call(scope, value, function (val) {
- validate(val, message);
+ validate(val, type);
});
} else {
- validate(validator.call(scope, value), message);
+ validate(validator.call(scope, value), type, message);
}
}
});
View
56 lib/utils.js
@@ -481,6 +481,62 @@ exports.expires = function expires (object) {
delete object.expires;
}
+/**
+ * Makes path more user friendly.
+ *
+ * If `message` contains special placeholder `{path}`, it will be
+ * replaced with normalized path.
+ *
+ * Example:
+ *
+ * name: {
+ * first: {
+ * type: String,
+ * required: true
+ * }
+ * }, // Name First
+ *
+ * your_dear_name: {
+ * type: String,
+ * required: true
+ * }, // Your Dear Name
+ *
+ * myBirthDate: {
+ * type: Date
+ * } // My Birth Date
+ *
+ * Provide your own error message instead of built-in one:
+ *
+ * name: {
+ * first: {
+ * type: String,
+ * required: [true, 'Please fill out "{path}" field.']
+ * } // Please fill out "Name First" field.
+ * }
+ *
+ * @param {String} path
+ * @param {String} message
+ * @return {String} normalized message
+ */
+
+exports.normalizeMessage = function normalizeMessage(path, message) {
+ var tokens = path
+ .replace(/([a-z0-9]){1}([A-Z])/g, '$1 $2')
+ .replace(/\_/g, ' ')
+ .toLowerCase()
+ .split('.');
+
+ var normalizedPath = '';
+ for (var i = 0; i < tokens.length; i++) {
+ var words = tokens[i].split(' ');
+ for (var j = 0; j < words.length; j++) {
+ normalizedPath += words[j].charAt(0).toUpperCase() + words[j].slice(1) + ' ';
+ }
+ }
+
+ return message.replace('{path}', normalizedPath.trim())
+};
+
exports.readPref = function readPref (pref, tags) {
if (Array.isArray(pref)) {
tags = pref[1];
View
10 test/document.test.js
@@ -744,7 +744,7 @@ describe('document:', function(){
t.req = undefined;
t.save(function (err) {
err = String(err);
- var invalid = /Validator "required" failed for path req/.test(err);
+ var invalid = /ValidationError: Req cannot be blank\./.test(err);
assert.ok(invalid);
t.req = 'it works again'
t.save(function (err) {
@@ -817,10 +817,10 @@ describe('document:', function(){
var M = db.model('validateSchema-array1', schema, collection);
var m = new M({ name: 'gh1109-1' });
m.save(function (err) {
- assert.ok(/"required" failed for path arr/.test(err));
+ assert.ok(/ValidationError: Arr cannot be blank./.test(err.toString()));
m.arr = [];
m.save(function (err) {
- assert.ok(/"required" failed for path arr/.test(err));
+ assert.ok(/ValidationError: Arr cannot be blank./.test(err.toString()));
m.arr.push('works');
m.save(function (err) {
assert.ifError(err);
@@ -860,7 +860,7 @@ describe('document:', function(){
})
})
- it('with both required + custom validator', function(){
+ it('with both required + custom validator', function(done){
function validator (val) {
called = true;
return val && val.length > 1
@@ -877,7 +877,7 @@ describe('document:', function(){
var M = db.model('validateSchema-array3', schema, collection);
var m = new M({ name: 'gh1109-3' });
m.save(function (err) {
- assert.ok(/"required" failed for path arr/.test(err));
+ assert.ok(/ValidationError: Arr cannot be blank./.test(err));
m.arr.push({nice: true});
m.save(function (err) {
assert.ok(/"BAM" failed for path arr/.test(err));
View
6 test/model.test.js
@@ -1114,9 +1114,9 @@ describe('model', function(){
assert.ok(err instanceof MongooseError);
assert.ok(err instanceof ValidationError);
assert.ok(err.errors['items.0.subs.0.required'] instanceof ValidatorError);
- assert.equal(err.errors['items.0.subs.0.required'].message,'Validator "required" failed for path required');
+ assert.equal(err.errors['items.0.subs.0.required'].message,'Required cannot be blank.');
assert.ok(post.errors['items.0.subs.0.required'] instanceof ValidatorError);
- assert.equal(post.errors['items.0.subs.0.required'].message,'Validator "required" failed for path required');
+ assert.equal(post.errors['items.0.subs.0.required'].message,'Required cannot be blank.');
assert.ok(!err.errors['items.0.required']);
assert.ok(!err.errors['items.0.required']);
@@ -1130,7 +1130,7 @@ describe('model', function(){
assert.ok(err);
assert.ok(err.errors);
assert.ok(err.errors['items.0.required'] instanceof ValidatorError);
- assert.equal(err.errors['items.0.required'].message,'Validator "required" failed for path required');
+ assert.equal(err.errors['items.0.required'].message,'Required cannot be blank.');
assert.ok(!err.errors['items.0.subs.0.required']);
assert.ok(!err.errors['items.0.subs.0.required']);
View
2  test/schema.test.js
@@ -565,7 +565,7 @@ describe('schema', function(){
var M = db.model('castingStringArrayWithUndefined', schema);
M.find({ arr: { $in: [undefined] }}, function (err) {
db.close();
- assert.equal(err && err.message, 'Cast to string failed for value "undefined"');
+ assert.equal(err && err.message, 'String must be a string.');
done();
});
});
View
2  test/types.document.test.js
@@ -75,7 +75,7 @@ describe('types.document', function(){
a.save(function(err){
assert.ok(a.__parent._validationError instanceof ValidationError);
assert.equal(a.__parent.errors['jsconf.ar.0.work'].name, 'ValidatorError');
- assert.equal(a.__parent._validationError.toString(), 'ValidationError: Validator "required" failed for path test, Validator failed for path work');
+ assert.equal(a.__parent._validationError.toString(), 'ValidationError: Test cannot be blank., Validator failed for path work');
done();
});
});
Something went wrong with that request. Please try again.