From 9bbd873ff74f4000fa658e31fd82b9ca99388b5e Mon Sep 17 00:00:00 2001 From: Aaron Heckmann Date: Thu, 26 Apr 2012 16:47:19 -0700 Subject: [PATCH] fix subdoc validation error paths subdoc validation errors are now bubbled up to their parent document and no longer passed to their local callback. closes #725 --- lib/types/embedded.js | 17 +++++++++++++++++ test/model.test.js | 13 ++++++++++--- test/types.buffer.test.js | 4 ++-- test/types.document.test.js | 17 ++++++++++++++--- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/lib/types/embedded.js b/lib/types/embedded.js index dff1fe331a8..cdbe3bb7fe5 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -96,6 +96,23 @@ EmbeddedDocument.prototype.inspect = function () { return inspect(this.toObject()); }; +/** + * Invalidate + * + * Report accurate embedded paths for invalidation. + * + * @param {String} path of the field to invalidate + * @param {String/Error} error of the path. + * @api public + */ + +EmbeddedDocument.prototype.invalidate = function (path, err) { + var index = this.parentArray.indexOf(this); + var parentPath = this.parentArray._path; + var fullPath = [parentPath, index, path].join('.'); + this.parent.invalidate(fullPath, err); +} + /** * Module exports. */ diff --git a/test/model.test.js b/test/model.test.js index 7b2697e1904..14a9216269a 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -1273,8 +1273,12 @@ module.exports = { }, 'test validation in subdocuments': function(){ + + var Subsubdocs= new Schema({ required: { type: String, required: true }}); + var Subdocs = new Schema({ required: { type: String, required: true } + , subs: [Subsubdocs] }); mongoose.model('TestSubdocumentsValidation', new Schema({ @@ -1286,15 +1290,18 @@ module.exports = { var post = new TestSubdocumentsValidation(); - post.get('items').push({ required: '' }); + post.get('items').push({ required: '', subs: [{required: ''}] }); post.save(function(err){ err.should.be.an.instanceof(MongooseError); err.should.be.an.instanceof(ValidationError); - err.errors.required.should.be.an.instanceof(ValidatorError); - err.errors.required.message.should.eql('Validator "required" failed for path required'); + err.errors['items.0.subs.0.required'].should.be.an.instanceof(ValidatorError); + err.errors['items.0.subs.0.required'].message.should.eql('Validator "required" failed for path required'); + err.errors['items.0.required'].should.be.an.instanceof(ValidatorError); + err.errors['items.0.required'].message.should.eql('Validator "required" failed for path required'); post.get('items')[0].set('required', true); + post.items[0].subs[0].set('required', true); post.save(function(err){ should.strictEqual(err, null); db.close(); diff --git a/test/types.buffer.test.js b/test/types.buffer.test.js index 7b94b011c5d..90718bacdfd 100644 --- a/test/types.buffer.test.js +++ b/test/types.buffer.test.js @@ -78,11 +78,11 @@ module.exports = { t.sub.push({ name: 'Friday Friday' }); t.save(function (err) { err.message.should.eql('Validation failed'); - err.errors.buf.type.should.equal('required'); + err.errors['sub.0.buf'].type.should.equal('required'); t.sub[0].buf = new Buffer("well well"); t.save(function (err) { err.message.should.eql('Validation failed'); - err.errors.buf.type.should.equal('valid failed'); + err.errors['sub.0.buf'].type.should.equal('valid failed'); t.sub[0].buf = new Buffer("well well well"); t.validate(function (err) { diff --git a/test/types.document.test.js b/test/types.document.test.js index a4224039099..67eda6881e7 100644 --- a/test/types.document.test.js +++ b/test/types.document.test.js @@ -17,8 +17,18 @@ var should = require('should') * Setup. */ +function Dummy () { + mongoose.Document.call(this, {}); +} +Dummy.prototype.__proto__ = mongoose.Document.prototype; +Dummy.prototype.schema = new Schema; + function Subdocument () { - EmbeddedDocument.call(this, {}, new DocumentArray); + var arr = new DocumentArray; + arr._path = 'jsconf.ar' + arr._parent = new Dummy; + arr[0] = this; + EmbeddedDocument.call(this, {}, arr); }; /** @@ -63,8 +73,9 @@ module.exports = { a.set('work', 'nope'); a.save(function(err){ - err.should.be.an.instanceof(ValidationError); - err.toString().should.eql('ValidationError: Validator "required" failed for path test, Validator failed for path work'); + a.parent._validationError.should.be.an.instanceof(ValidationError); + a.parent.errors['jsconf.ar.0.work'].name.should.eql('ValidatorError'); + a.parent._validationError.toString().should.eql('ValidationError: Validator "required" failed for path test, Validator failed for path work'); }); },