diff --git a/lib/document.js b/lib/document.js index 7aea1630586..d528ed40c91 100644 --- a/lib/document.js +++ b/lib/document.js @@ -975,6 +975,18 @@ Document.prototype.validate = function (cb) { var validating = {} , total = 0; + // gh-661: if a whole array is modified, make sure to run validation on all + // the children as well + for (var i = 0; i < paths.length; ++i) { + var path = paths[i]; + var val = self.getValue(path); + if (val instanceof Array && !Buffer.isBuffer(val)) { + var numElements = val.length; + for (var j = 0; j < numElements; ++j) { + paths.push(path + '.' + j); + } + } + } paths.forEach(validatePath); return promise; diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index d8c126de395..b894017f598 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -694,5 +694,32 @@ describe('schema', function(){ }); }); }); + + it('should allow an array of enums (gh-661)', function(done) { + var validBreakfastFoods = ['bacon', 'eggs', 'steak', 'coffee', 'butter']; + var breakfastSchema = new Schema({ + foods: [{ type: String, enum: validBreakfastFoods }] + }); + var Breakfast = mongoose.model('gh-661', breakfastSchema, 'gh-661'); + + var goodBreakfast = new Breakfast({ foods: ['eggs', 'bacon'] }); + goodBreakfast.validate(function(error) { + assert.ifError(error); + + var badBreakfast = new Breakfast({ foods: ['tofu', 'waffles', 'coffee'] }); + badBreakfast.validate(function(error) { + assert.ok(error); + assert.ok(error.errors['foods.0']); + assert.equal(error.errors['foods.0'].message, + '`tofu` is not a valid enum value for path `foods`.'); + assert.ok(error.errors['foods.1']); + assert.equal(error.errors['foods.1'].message, + '`waffles` is not a valid enum value for path `foods`.'); + assert.ok(!error.errors['foods.2']); + + done(); + }); + }); + }); }); });