mongoose
Version:
Mongoose MongoDB ODM
1,592 lines (1,344 loc) • 48.4 kB
JavaScript
/**
* Test dependencies.
*/
var start = require('./common')
, assert = require('assert')
, mongoose = start.mongoose
, random = require('../lib/utils').random
, Schema = mongoose.Schema
, ObjectId = Schema.ObjectId
, DocObjectId = mongoose.Types.ObjectId
/**
* Setup.
*/
/**
* User schema.
*/
var User = new Schema({
name : String
, email : String
, gender : { type: String, enum: ['male', 'female'], default: 'male' }
, age : { type: Number, default: 21 }
, blogposts : [{ type: ObjectId, ref: 'RefBlogPost' }]
});
/**
* Comment subdocument schema.
*/
var Comment = new Schema({
_creator : { type: ObjectId, ref: 'RefUser' }
, content : String
});
/**
* Blog post schema.
*/
var BlogPost = new Schema({
_creator : { type: ObjectId, ref: 'RefUser' }
, title : String
, comments : [Comment]
, fans : [{ type: ObjectId, ref: 'RefUser' }]
});
var posts = 'blogposts_' + random()
, users = 'users_' + random();
mongoose.model('RefBlogPost', BlogPost);
mongoose.model('RefUser', User);
mongoose.model('RefAlternateUser', User);
/**
* Tests.
*/
describe('model: ref:', function(){
it('populating a single ref', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users)
User.create({
name : 'Guillermo'
, email : 'rauchg@gmail.com'
}, function (err, creator) {
assert.ifError(err);
BlogPost.create({
title : 'woot'
, _creator : creator
}, function (err, post) {
assert.ifError(err);
BlogPost
.findById(post._id)
.populate('_creator')
.exec(function (err, post) {
db.close();
assert.ifError(err);
assert.ok(post._creator instanceof User);
assert.equal(post._creator.name, 'Guillermo');
assert.equal(post._creator.email, 'rauchg@gmail.com');
done();
});
});
});
})
it('an error in single ref population propagates', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts + '1')
, User = db.model('RefUser', users + '1');
User.create({
name: 'Guillermo'
, email: 'rauchg@gmail.com'
}, function (err, creator) {
assert.ifError(err);
BlogPost.create({
title : 'woot'
, _creator : creator
}, function (err, post) {
assert.ifError(err);
var origFind = User.findOne;
// mock an error
User.findOne = function () {
var args = Array.prototype.map.call(arguments, function (arg) {
return 'function' == typeof arg ? function () {
arg(new Error('woot'));
} : arg;
});
return origFind.apply(this, args);
};
BlogPost
.findById(post._id)
.populate('_creator')
.exec(function (err, post) {
db.close();
assert.ok(err instanceof Error);
assert.equal('woot', err.message);
done()
});
});
});
})
it('populating with partial fields selection', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users);
User.create({
name : 'Guillermo'
, email : 'rauchg@gmail.com'
}, function (err, creator) {
assert.ifError(err);
BlogPost.create({
title : 'woot'
, _creator : creator
}, function (err, post) {
assert.ifError(err);
BlogPost
.findById(post._id)
.populate('_creator', 'email')
.exec(function (err, post) {
db.close();
assert.ifError(err);
assert.ok(post._creator instanceof User);
assert.equal(false, post._creator.isInit('name'));
assert.equal(post._creator.email,'rauchg@gmail.com');
done();
});
});
});
});
it('population of single oid with partial field selection and filter', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users);
User.create({
name : 'Banana'
, email : 'cats@example.com'
}, function (err, creator) {
assert.ifError(err);
BlogPost.create({
title : 'woot'
, _creator : creator
}, function (err, post) {
assert.ifError(err);
BlogPost
.findById(post._id)
.populate('_creator', 'email', { name: 'Peanut' })
.exec(function (err, post) {
assert.ifError(err);
assert.strictEqual(post._creator, null);
BlogPost
.findById(post._id)
.populate('_creator', 'email', { name: 'Banana' })
.exec(function (err, post) {
db.close();
assert.ifError(err);
assert.ok(post._creator instanceof User);
assert.equal(false,post._creator.isInit('name'));
assert.equal(post._creator.email,'cats@example.com');
done();
});
});
});
});
})
it('population and changing a reference', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users);
User.create({
name : 'Guillermo'
, email : 'rauchg@gmail.com'
}, function (err, creator) {
assert.ifError(err);
BlogPost.create({
title : 'woot'
, _creator : creator
}, function (err, post) {
assert.ifError(err);
BlogPost
.findById(post._id)
.populate('_creator')
.exec(function (err, post) {
assert.ifError(err);
assert.ok(post._creator instanceof User);
assert.equal(post._creator.name,'Guillermo');
assert.equal(post._creator.email,'rauchg@gmail.com');
User.create({
name : 'Aaron'
, email : 'aaron.heckmann@10gen.com'
}, function (err, newCreator) {
assert.ifError(err);
post._creator = newCreator._id;
post.save(function (err) {
assert.ifError(err);
BlogPost
.findById(post._id)
.populate('_creator')
.exec(function (err, post) {
db.close();
assert.ifError(err);
assert.equal(post._creator.name,'Aaron');
assert.equal(post._creator.email,'aaron.heckmann@10gen.com');
done();
});
});
});
});
});
});
})
it('populating with partial fields selection and changing ref', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users);
User.create({
name : 'Guillermo'
, email : 'rauchg@gmail.com'
}, function (err, creator) {
assert.ifError(err);
BlogPost.create({
title : 'woot'
, _creator : creator
}, function (err, post) {
assert.ifError(err);
BlogPost
.findById(post._id)
.populate('_creator', {'name': 1})
.exec(function (err, post) {
assert.ifError(err);
assert.ok(post._creator instanceof User);
assert.equal(post._creator.name,'Guillermo');
User.create({
name : 'Aaron'
, email : 'aaron@learnboost.com'
}, function (err, newCreator) {
assert.ifError(err);
post._creator = newCreator._id;
post.save(function (err) {
assert.ifError(err);
BlogPost
.findById(post._id)
.populate('_creator', '-email')
.exec(function (err, post) {
db.close();
assert.ifError(err);
assert.equal(post._creator.name,'Aaron');
assert.ok(!post._creator.email);
done();
});
});
});
});
});
});
});
it('populating an array of refs and fetching many', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users);
User.create({
name : 'Fan 1'
, email : 'fan1@learnboost.com'
}, function (err, fan1) {
assert.ifError(err);
User.create({
name : 'Fan 2'
, email : 'fan2@learnboost.com'
}, function (err, fan2) {
assert.ifError(err);
BlogPost.create({
title : 'Woot'
, fans : [fan1, fan2]
}, function (err, post1) {
assert.ifError(err);
BlogPost.create({
title : 'Woot'
, fans : [fan2, fan1]
}, function (err, post2) {
assert.ifError(err);
BlogPost
.find({ _id: { $in: [post1._id, post2._id ] } })
.populate('fans')
.exec(function (err, blogposts) {
db.close();
assert.ifError(err);
assert.equal(blogposts[0].fans[0].name,'Fan 1');
assert.equal(blogposts[0].fans[0].email,'fan1@learnboost.com');
assert.equal(blogposts[0].fans[1].name,'Fan 2');
assert.equal(blogposts[0].fans[1].email,'fan2@learnboost.com');
assert.equal(blogposts[1].fans[0].name,'Fan 2');
assert.equal(blogposts[1].fans[0].email,'fan2@learnboost.com');
assert.equal(blogposts[1].fans[1].name,'Fan 1');
assert.equal(blogposts[1].fans[1].email,'fan1@learnboost.com');
done();
});
});
});
});
});
})
it('an error in array reference population propagates', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts + '2')
, User = db.model('RefUser', users + '2');
User.create({
name : 'Fan 1'
, email : 'fan1@learnboost.com'
}, function (err, fan1) {
assert.ifError(err);
User.create({
name : 'Fan 2'
, email : 'fan2@learnboost.com'
}, function (err, fan2) {
assert.ifError(err);
BlogPost.create({
title : 'Woot'
, fans : [fan1, fan2]
}, function (err, post1) {
assert.ifError(err);
BlogPost.create({
title : 'Woot'
, fans : [fan2, fan1]
}, function (err, post2) {
assert.ifError(err);
// mock an error
var origFind = User.find;
User.find = function () {
var args = Array.prototype.map.call(arguments, function (arg) {
return 'function' == typeof arg ? function () {
arg(new Error('woot 2'));
} : arg;
});
return origFind.apply(this, args);
};
BlogPost
.find({ $or: [{ _id: post1._id }, { _id: post2._id }] })
.populate('fans')
.exec(function (err, blogposts) {
db.close();
assert.ok(err instanceof Error);
assert.equal(err.message,'woot 2');
done();
});
});
});
});
});
})
it('populating an array of references with fields selection', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users);
User.create({
name : 'Fan 1'
, email : 'fan1@learnboost.com'
}, function (err, fan1) {
assert.ifError(err);
User.create({
name : 'Fan 2'
, email : 'fan2@learnboost.com'
}, function (err, fan2) {
assert.ifError(err);
BlogPost.create({
title : 'Woot'
, fans : [fan1, fan2]
}, function (err, post1) {
assert.ifError(err);
BlogPost.create({
title : 'Woot'
, fans : [fan2, fan1]
}, function (err, post2) {
assert.ifError(err);
BlogPost
.find({ _id: { $in: [post1._id, post2._id ] } })
.populate('fans', 'name')
.exec(function (err, blogposts) {
db.close();
assert.ifError(err);
assert.equal(blogposts[0].fans[0].name,'Fan 1');
assert.equal(blogposts[0].fans[0].isInit('email'), false);
assert.equal(blogposts[0].fans[1].name, 'Fan 2');
assert.equal(blogposts[0].fans[1].isInit('email'), false);
assert.strictEqual(blogposts[0].fans[1].email, undefined);
assert.equal(blogposts[1].fans[0].name, 'Fan 2');
assert.equal(blogposts[1].fans[0].isInit('email'), false);
assert.equal(blogposts[1].fans[1].name, 'Fan 1');
assert.equal(blogposts[1].fans[1].isInit('email'), false);
done();
});
});
});
});
});
})
it('populating an array of references and filtering', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users);
User.create({
name : 'Fan 1'
, email : 'fan1@learnboost.com'
}, function (err, fan1) {
assert.ifError(err);
User.create({
name : 'Fan 2'
, email : 'fan2@learnboost.com'
, gender : 'female'
}, function (err, fan2) {
assert.ifError(err);
User.create({
name : 'Fan 3'
, email : 'fan3@learnboost.com'
, gender : 'female'
}, function (err, fan3) {
assert.ifError(err);
BlogPost.create({
title : 'Woot'
, fans : [fan1, fan2, fan3]
}, function (err, post1) {
assert.ifError(err);
BlogPost.create({
title : 'Woot'
, fans : [fan3, fan2, fan1]
}, function (err, post2) {
assert.ifError(err);
BlogPost
.find({ _id: { $in: [post1._id, post2._id ] } })
.populate('fans', '', { gender: 'female', _id: { $in: [fan2] }})
.exec(function (err, blogposts) {
assert.ifError(err);
assert.equal(blogposts[0].fans.length, 1);
assert.equal(blogposts[0].fans[0].gender, 'female');
assert.equal(blogposts[0].fans[0].name,'Fan 2');
assert.equal(blogposts[0].fans[0].email,'fan2@learnboost.com');
assert.equal(blogposts[1].fans.length, 1);
assert.equal(blogposts[1].fans[0].gender,'female');
assert.equal(blogposts[1].fans[0].name,'Fan 2');
assert.equal(blogposts[1].fans[0].email,'fan2@learnboost.com');
BlogPost
.find({ _id: { $in: [post1._id, post2._id ] } })
.populate('fans', false, { gender: 'female' })
.exec(function (err, blogposts) {
db.close();
assert.ifError(err);
assert.strictEqual(blogposts[0].fans.length, 2);
assert.equal(blogposts[0].fans[0].gender,'female');
assert.equal(blogposts[0].fans[0].name,'Fan 2');
assert.equal(blogposts[0].fans[0].email,'fan2@learnboost.com');
assert.equal(blogposts[0].fans[1].gender,'female');
assert.equal(blogposts[0].fans[1].name,'Fan 3');
assert.equal(blogposts[0].fans[1].email,'fan3@learnboost.com');
assert.strictEqual(blogposts[1].fans.length, 2);
assert.equal(blogposts[1].fans[0].gender,'female');
assert.equal(blogposts[1].fans[0].name,'Fan 3');
assert.equal(blogposts[1].fans[0].email,'fan3@learnboost.com');
assert.equal(blogposts[1].fans[1].gender,'female');
assert.equal(blogposts[1].fans[1].name,'Fan 2');
assert.equal(blogposts[1].fans[1].email,'fan2@learnboost.com');
done();
});
});
});
});
});
});
});
});
it('populating an array of references and multi-filtering', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users);
User.create({
name : 'Fan 1'
, email : 'fan1@learnboost.com'
}, function (err, fan1) {
assert.ifError(err);
User.create({
name : 'Fan 2'
, email : 'fan2@learnboost.com'
, gender : 'female'
}, function (err, fan2) {
assert.ifError(err);
User.create({
name : 'Fan 3'
, email : 'fan3@learnboost.com'
, gender : 'female'
, age : 25
}, function (err, fan3) {
assert.ifError(err);
BlogPost.create({
title : 'Woot'
, fans : [fan1, fan2, fan3]
}, function (err, post1) {
assert.ifError(err);
BlogPost.create({
title : 'Woot'
, fans : [fan3, fan2, fan1]
}, function (err, post2) {
assert.ifError(err);
BlogPost
.find({ _id: { $in: [post1._id, post2._id ] } })
.populate('fans', undefined, { _id: fan3 })
.exec(function (err, blogposts) {
assert.ifError(err);
assert.equal(blogposts[0].fans.length, 1);
assert.equal(blogposts[0].fans[0].gender,'female');
assert.equal(blogposts[0].fans[0].name,'Fan 3');
assert.equal(blogposts[0].fans[0].email,'fan3@learnboost.com');
assert.equal(blogposts[0].fans[0].age, 25);
assert.equal(blogposts[1].fans.length,1);
assert.equal(blogposts[1].fans[0].gender,'female');
assert.equal(blogposts[1].fans[0].name,'Fan 3');
assert.equal(blogposts[1].fans[0].email,'fan3@learnboost.com');
assert.equal(blogposts[1].fans[0].age, 25);
BlogPost
.find({ _id: { $in: [post1._id, post2._id ] } })
.populate('fans', 0, { gender: 'female' })
.exec(function (err, blogposts) {
db.close();
assert.ifError(err);
assert.equal(blogposts[0].fans.length, 2);
assert.equal(blogposts[0].fans[0].gender,'female');
assert.equal(blogposts[0].fans[0].name,'Fan 2');
assert.equal(blogposts[0].fans[0].email, 'fan2@learnboost.com');
assert.equal(blogposts[0].fans[1].gender, 'female');
assert.equal(blogposts[0].fans[1].name, 'Fan 3');
assert.equal(blogposts[0].fans[1].email, 'fan3@learnboost.com');
assert.equal(blogposts[0].fans[1].age, 25);
assert.equal(blogposts[1].fans.length, 2);
assert.equal(blogposts[1].fans[0].gender, 'female');
assert.equal(blogposts[1].fans[0].name, 'Fan 3');
assert.equal(blogposts[1].fans[0].email, 'fan3@learnboost.com');
assert.equal(blogposts[1].fans[0].age, 25);
assert.equal(blogposts[1].fans[1].gender, 'female');
assert.equal(blogposts[1].fans[1].name, 'Fan 2');
assert.equal(blogposts[1].fans[1].email, 'fan2@learnboost.com');
done();
});
});
});
});
});
});
});
});
it('populating an array of references and multi-filtering with field selection', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users);
User.create({
name : 'Fan 1'
, email : 'fan1@learnboost.com'
}, function (err, fan1) {
assert.ifError(err);
User.create({
name : 'Fan 2'
, email : 'fan2@learnboost.com'
, gender : 'female'
}, function (err, fan2) {
assert.ifError(err);
User.create({
name : 'Fan 3'
, email : 'fan3@learnboost.com'
, gender : 'female'
, age : 25
}, function (err, fan3) {
assert.ifError(err);
BlogPost.create({
title : 'Woot'
, fans : [fan1, fan2, fan3]
}, function (err, post1) {
assert.ifError(err);
BlogPost.create({
title : 'Woot'
, fans : [fan3, fan2, fan1]
}, function (err, post2) {
assert.ifError(err);
BlogPost
.find({ _id: { $in: [post1._id, post2._id ] } })
.populate('fans', 'name email', { gender: 'female', age: 25 })
.exec(function (err, blogposts) {
db.close();
assert.ifError(err);
assert.strictEqual(blogposts[0].fans.length, 1);
assert.equal(blogposts[0].fans[0].name,'Fan 3');
assert.equal(blogposts[0].fans[0].email,'fan3@learnboost.com');
assert.equal(blogposts[0].fans[0].isInit('email'), true)
assert.equal(blogposts[0].fans[0].isInit('gender'), false);
assert.equal(blogposts[0].fans[0].isInit('age'), false);
assert.strictEqual(blogposts[1].fans.length, 1);
assert.equal(blogposts[1].fans[0].name,'Fan 3');
assert.equal(blogposts[1].fans[0].email,'fan3@learnboost.com');
assert.equal(blogposts[1].fans[0].isInit('email'), true);
assert.equal(blogposts[1].fans[0].isInit('gender'), false);
assert.equal(blogposts[1].fans[0].isInit('age'), false)
done()
});
});
});
});
});
});
})
it('populating an array of refs changing one and removing one', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users);
User.create({
name : 'Fan 1'
, email : 'fan1@learnboost.com'
}, {
name : 'Fan 2'
, email : 'fan2@learnboost.com'
}, {
name : 'Fan 3'
, email : 'fan3@learnboost.com'
}, {
name : 'Fan 4'
, email : 'fan4@learnboost.com'
}, function (err, fan1, fan2, fan3, fan4) {
assert.ifError(err);
BlogPost.create({
title : 'Woot'
, fans : [fan1, fan2]
}, {
title : 'Woot'
, fans : [fan2, fan1]
}, function (err, post1, post2) {
assert.ifError(err);
BlogPost
.find({ _id: { $in: [post1._id, post2._id ] } })
.populate('fans', 'name')
.exec(function (err, blogposts) {
assert.ifError(err);
assert.equal(blogposts[0].fans[0].name,'Fan 1');
assert.equal(blogposts[0].fans[0].isInit('email'), false);
assert.equal(blogposts[0].fans[1].name,'Fan 2');
assert.equal(blogposts[0].fans[1].isInit('email'), false);
assert.equal(blogposts[1].fans[0].name,'Fan 2');
assert.equal(blogposts[1].fans[0].isInit('email'), false);
assert.equal(blogposts[1].fans[1].name,'Fan 1');
assert.equal(blogposts[1].fans[1].isInit('email'),false);
blogposts[1].fans = [fan3, fan4];
blogposts[1].save(function (err) {
assert.ifError(err);
BlogPost
.findById(blogposts[1]._id, '', { populate: ['fans'] })
.exec(function (err, post) {
assert.ifError(err);
assert.equal(post.fans[0].name,'Fan 3');
assert.equal(post.fans[1].name,'Fan 4');
post.fans.splice(0, 1);
post.save(function (err) {
assert.ifError(err);
BlogPost
.findById(post._id)
.populate('fans')
.exec(function (err, post) {
db.close();
assert.ifError(err);
assert.equal(post.fans.length,1);
assert.equal(post.fans[0].name,'Fan 4');
done();
});
});
});
});
});
});
});
})
it('populating sub docs', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users);
User.create({ name: 'User 1' }, function (err, user1) {
assert.ifError(err);
User.create({ name: 'User 2' }, function (err, user2) {
assert.ifError(err);
BlogPost.create({
title: 'Woot'
, _creator: user1._id
, comments: [
{ _creator: user1._id, content: 'Woot woot' }
, { _creator: user2._id, content: 'Wha wha' }
]
}, function (err, post) {
assert.ifError(err);
BlogPost
.findById(post._id)
.populate('_creator')
.populate('comments._creator')
.exec(function (err, post) {
db.close();
assert.ifError(err);
assert.equal(post._creator.name,'User 1');
assert.equal(post.comments[0]._creator.name,'User 1');
assert.equal(post.comments[1]._creator.name,'User 2');
done();
});
});
});
});
})
it('populating subdocuments partially', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users);
User.create({
name : 'User 1'
, email : 'user1@learnboost.com'
}, function (err, user1) {
assert.ifError(err);
User.create({
name : 'User 2'
, email : 'user2@learnboost.com'
}, function (err, user2) {
assert.ifError(err);
var post = BlogPost.create({
title: 'Woot'
, comments: [
{ _creator: user1, content: 'Woot woot' }
, { _creator: user2, content: 'Wha wha' }
]
}, function (err, post) {
assert.ifError(err);
BlogPost
.findById(post._id)
.populate('comments._creator', 'email')
.exec(function (err, post) {
db.close();
assert.ifError(err);
assert.equal(post.comments[0]._creator.email,'user1@learnboost.com');
assert.equal(post.comments[0]._creator.isInit('name'), false);
assert.equal(post.comments[1]._creator.email,'user2@learnboost.com');
assert.equal(post.comments[1]._creator.isInit('name'), false);
done();
});
});
});
});
})
it('populating subdocuments partially with conditions', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users);
User.create({
name : 'User 1'
, email : 'user1@learnboost.com'
}, function (err, user1) {
assert.ifError(err);
User.create({
name : 'User 2'
, email : 'user2@learnboost.com'
}, function (err, user2) {
assert.ifError(err);
var post = BlogPost.create({
title: 'Woot'
, comments: [
{ _creator: user1, content: 'Woot woot' }
, { _creator: user2, content: 'Wha wha' }
]
}, function (err, post) {
assert.ifError(err);
BlogPost
.findById(post._id)
.populate('comments._creator', {'email': 1}, { name: /User/ })
.exec(function (err, post) {
db.close();
assert.ifError(err);
assert.equal(post.comments[0]._creator.email,'user1@learnboost.com');
assert.equal(post.comments[0]._creator.isInit('name'),false);
assert.equal(post.comments[1]._creator.email,'user2@learnboost.com');
assert.equal(post.comments[1]._creator.isInit('name'), false);
done()
});
});
});
});
})
it('populating subdocs with invalid/missing subproperties', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users);
User.create({
name : 'T-100'
, email : 'terminator100@learnboost.com'
}, function (err, user1) {
assert.ifError(err);
User.create({
name : 'T-1000'
, email : 'terminator1000@learnboost.com'
}, function (err, user2) {
assert.ifError(err);
var post = BlogPost.create({
title: 'Woot'
, comments: [
{ _creator: null, content: 'Woot woot' }
, { _creator: user2, content: 'Wha wha' }
]
}, function (err, post) {
assert.ifError(err);
// invalid subprop
BlogPost
.findById(post._id)
.populate('comments._idontexist', 'email')
.exec(function (err, post) {
assert.ifError(err);
assert.ok(post);
assert.equal(post.comments.length, 2);
assert.strictEqual(post.comments[0]._creator, null);
assert.equal(post.comments[1]._creator.toString(),user2.id);
// subprop is null in a doc
BlogPost
.findById(post._id)
.populate('comments._creator', 'email')
.exec(function (err, post) {
db.close();
assert.ifError(err);
assert.ok(post);
assert.equal(post.comments.length,2);
assert.strictEqual(post.comments[0]._creator, null);
assert.strictEqual(post.comments[0].content, 'Woot woot');
assert.equal(post.comments[1]._creator.email,'terminator1000@learnboost.com');
assert.equal(post.comments[1]._creator.isInit('name'), false);
assert.equal(post.comments[1].content,'Wha wha');
done();
});
});
});
});
});
})
it('populating subdocuments partially with empty array (gh-481)', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, worked = false;
var post = BlogPost.create({
title: 'Woot'
, comments: [] // EMPTY ARRAY
}, function (err, post) {
assert.ifError(err);
BlogPost
.findById(post._id)
.populate('comments._creator', 'email')
.exec(function (err, returned) {
db.close();
assert.ifError(err);
assert.equal(returned.id,post.id);
done();
});
});
});
it('populating subdocuments with array including nulls', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users)
var user = new User({ name: 'hans zimmer' });
user.save(function (err) {
assert.ifError(err);
var post = BlogPost.create({
title: 'Woot'
, fans: []
}, function (err, post) {
assert.ifError(err);
// shove some uncasted vals
BlogPost.collection.update({ _id: post._id }, { $set: { fans: [null, undefined, user.id, null] } }, function (err) {
assert.ifError(err);
BlogPost
.findById(post._id)
.populate('fans', 'name')
.exec(function (err, returned) {
db.close();
assert.ifError(err);
assert.equal(returned.id,post.id);
assert.equal(returned.fans.length,1);
done();
});
})
});
});
})
it('populating more than one array at a time', function(done){
var db = start()
, User = db.model('RefUser', users)
, M = db.model('PopMultiSubDocs', new Schema({
users: [{ type: ObjectId, ref: 'RefUser' }]
, fans: [{ type: ObjectId, ref: 'RefUser' }]
, comments: [Comment]
}))
User.create({
email : 'fan1@learnboost.com'
}, {
name : 'Fan 2'
, email : 'fan2@learnboost.com'
, gender : 'female'
}, {
name: 'Fan 3'
}, function (err, fan1, fan2, fan3) {
assert.ifError(err);
M.create({
users: [fan3]
, fans: [fan1]
, comments: [
{ _creator: fan1, content: 'bejeah!' }
, { _creator: fan2, content: 'chickfila' }
]
}, {
users: [fan1]
, fans: [fan2]
, comments: [
{ _creator: fan3, content: 'hello' }
, { _creator: fan1, content: 'world' }
]
}, function (err, post1, post2) {
assert.ifError(err);
M.where('_id').in([post1, post2])
.populate('fans', 'name', { gender: 'female' })
.populate('users', 'name', { gender: 'male' })
.populate('comments._creator', 'email', { name: null })
.exec(function (err, posts) {
db.close();
assert.ifError(err);
assert.ok(posts);
assert.equal(posts.length,2);
var p1 = posts[0];
var p2 = posts[1];
assert.strictEqual(p1.fans.length, 0);
assert.strictEqual(p2.fans.length, 1);
assert.equal(p2.fans[0].name,'Fan 2');
assert.equal(p2.fans[0].isInit('email'), false);
assert.equal(p2.fans[0].isInit('gender'), false);
assert.equal(p1.comments.length,2);
assert.equal(p2.comments.length,2);
assert.ok(p1.comments[0]._creator.email);
assert.ok(!p2.comments[0]._creator);
assert.equal(p1.comments[0]._creator.email,'fan1@learnboost.com');
assert.equal(p2.comments[1]._creator.email,'fan1@learnboost.com');
assert.equal(p1.comments[0]._creator.isInit('name'), false);
assert.equal(p2.comments[1]._creator.isInit('name'), false);
assert.equal(p1.comments[0].content,'bejeah!');
assert.equal(p2.comments[1].content,'world');
assert.ok(!p1.comments[1]._creator);
assert.ok(!p2.comments[0]._creator);
assert.equal(p1.comments[1].content,'chickfila');
assert.equal(p2.comments[0].content,'hello');
done();
});
});
});
})
it('populating multiple children of a sub-array at a time', function(done){
var db = start()
, User = db.model('RefUser', users)
, BlogPost = db.model('RefBlogPost', posts)
, Inner = new Schema({
user: { type: ObjectId, ref: 'RefUser' }
, post: { type: ObjectId, ref: 'RefBlogPost' }
})
, I = db.model('PopMultiChildrenOfSubDocInner', Inner)
var M = db.model('PopMultiChildrenOfSubDoc', new Schema({
kids: [Inner]
}))
User.create({
name : 'Fan 1'
, email : 'fan1@learnboost.com'
, gender : 'male'
}, {
name : 'Fan 2'
, email : 'fan2@learnboost.com'
, gender : 'female'
}, function (err, fan1, fan2) {
assert.ifError(err);
BlogPost.create({
title : 'woot'
}, {
title : 'yay'
}, function (err, post1, post2) {
assert.ifError(err);
M.create({
kids: [
{ user: fan1, post: post1, y: 5 }
, { user: fan2, post: post2, y: 8 }
]
, x: 4
}, function (err, m1) {
assert.ifError(err);
M.findById(m1)
.populate('kids.user', "name")
.populate('kids.post', "title", { title: "woot" })
.exec(function (err, o) {
db.close();
assert.ifError(err);
assert.strictEqual(o.kids.length, 2);
var k1 = o.kids[0];
var k2 = o.kids[1];
assert.strictEqual(true, !k2.post);
assert.strictEqual(k1.user.name, "Fan 1");
assert.strictEqual(k1.user.email, undefined);
assert.strictEqual(k1.post.title, "woot");
assert.strictEqual(k2.user.name, "Fan 2");
done();
});
});
});
});
})
it('passing sort options to the populate method', function(done){
var db = start()
, P = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users);
User.create({ name: 'aaron', age: 10 }, { name: 'fan2', age: 8 }, { name: 'someone else', age: 3 },
function (err, fan1, fan2, fan3) {
assert.ifError(err);
P.create({ fans: [fan2, fan3, fan1] }, function (err, post) {
assert.ifError(err);
P.findById(post)
.populate('fans', null, null, { sort: 'name' })
.exec(function (err, post) {
assert.ifError(err);
assert.equal(post.fans.length,3);
assert.equal(post.fans[0].name,'aaron');
assert.equal(post.fans[1].name,'fan2');
assert.equal(post.fans[2].name,'someone else');
P.findById(post)
.populate('fans', 'name', null, { sort: [['name', -1]] })
.exec(function (err, post) {
assert.ifError(err);
assert.equal(post.fans.length,3);
assert.equal(post.fans[2].name,'aaron');
assert.strictEqual(undefined, post.fans[2].age)
assert.equal(post.fans[1].name,'fan2');
assert.strictEqual(undefined, post.fans[1].age)
assert.equal(post.fans[0].name,'someone else');
assert.strictEqual(undefined, post.fans[0].age)
P.findById(post)
.populate('fans', 'age', { age: { $gt: 3 }}, { sort: [['name', 'desc']] })
.exec(function (err, post) {
db.close();
assert.ifError(err);
assert.equal(post.fans.length,2);
assert.equal(post.fans[1].age.valueOf(),10);
assert.equal(post.fans[0].age.valueOf(),8);
done();
});
});
});
});
});
})
it('refs should cast to ObjectId from hexstrings', function(){
var BP = mongoose.model('RefBlogPost', BlogPost);
var bp = new BP;
bp._creator = new DocObjectId().toString();
assert.ok(bp._creator instanceof DocObjectId);
bp.set('_creator', new DocObjectId().toString());
assert.ok(bp._creator instanceof DocObjectId);
})
it('populate should work on String _ids', function(done){
var db = start();
var UserSchema = new Schema({
_id: String
, name: String
})
var NoteSchema = new Schema({
author: { type: String, ref: 'UserWithStringId' }
, body: String
})
var User = db.model('UserWithStringId', UserSchema, random())
var Note = db.model('NoteWithStringId', NoteSchema, random())
var alice = new User({_id: 'alice', name: "Alice"})
alice.save(function (err) {
assert.ifError(err);
var note = new Note({author: 'alice', body: "Buy Milk"});
note.save(function (err) {
assert.ifError(err);
Note.findById(note.id).populate('author').exec(function (err, note) {
db.close();
assert.ifError(err);
assert.equal(note.body,'Buy Milk');
assert.ok(note.author);
assert.equal(note.author.name,'Alice');
done();
});
});
})
});
it('populate should work on Number _ids', function(done){
var db = start();
var UserSchema = new Schema({
_id: Number
, name: String
})
var NoteSchema = new Schema({
author: { type: Number, ref: 'UserWithNumberId' }
, body: String
})
var User = db.model('UserWithNumberId', UserSchema, random())
var Note = db.model('NoteWithNumberId', NoteSchema, random())
var alice = new User({_id: 2359, name: "Alice"})
alice.save(function (err) {
assert.ifError(err);
var note = new Note({author: 2359, body: "Buy Milk"});
note.save(function (err) {
assert.ifError(err);
Note.findById(note.id).populate('author').exec(function (err, note) {
db.close();
assert.ifError(err);
assert.equal(note.body,'Buy Milk');
assert.ok(note.author);
assert.equal(note.author.name,'Alice');
done();
});
});
})
});
it('required works on ref fields (gh-577)', function(done){
var db = start();
var userSchema = new Schema({
email: {type: String, required: true}
});
var User = db.model('ObjectIdRefRequiredField', userSchema, random());
var numSchema = new Schema({ _id: Number, val: Number });
var Num = db.model('NumberRefRequired', numSchema, random());
var strSchema = new Schema({ _id: String, val: String });
var Str = db.model('StringRefRequired', strSchema, random());
var commentSchema = new Schema({
user: {type: ObjectId, ref: 'ObjectIdRefRequiredField', required: true}
, num: {type: Number, ref: 'NumberRefRequired', required: true}
, str: {type: String, ref: 'StringRefRequired', required: true}
, text: String
});
var Comment = db.model('CommentWithRequiredField', commentSchema);
var pending = 3;
var string = new Str({ _id: 'my string', val: 'hello' });
var number = new Num({ _id: 1995, val: 234 });
var user = new User({ email: 'test' });
string.save(next);
number.save(next);
user.save(next);
function next (err) {
assert.strictEqual(null, err);
if (--pending) return;
var comment = new Comment({
text: 'test'
});
comment.save(function (err) {
assert.equal('Validation failed', err && err.message);
assert.ok('num' in err.errors);
assert.ok('str' in err.errors);
assert.ok('user' in err.errors);
assert.equal(err.errors.num.type,'required');
assert.equal(err.errors.str.type,'required');
assert.equal(err.errors.user.type,'required');
comment.user = user;
comment.num = 1995;
comment.str = 'my string';
comment.save(function (err, comment) {
assert.strictEqual(null, err);
Comment
.findById(comment.id)
.populate('user')
.populate('num')
.populate('str')
.exec(function (err, comment) {
assert.ifError(err);
comment.set({text: 'test2'});
comment.save(function (err, comment) {
db.close();
assert.ifError(err);
done();
});
});
});
});
}
});
it('populate works with schemas with both id and _id defined', function(done){
var db =start()
, S1 = new Schema({ id: String })
, S2 = new Schema({ things: [{ type: ObjectId, ref: '_idAndid' }]})
var M1 = db.model('_idAndid', S1);
var M2 = db.model('populateWorksWith_idAndidSchemas', S2);
M1.create(
{ id: "The Tiger That Isn't" }
, { id: "Users Guide To The Universe" }
, function (err, a, b) {
assert.ifError(err);
var m2 = new M2({ things: [a, b]});
m2.save(function (err) {
assert.ifError(err);
M2.findById(m2).populate('things').exec(function (err, doc) {
db.close();
assert.ifError(err);
assert.equal(doc.things.length,2);
assert.equal(doc.things[0].id,"The Tiger That Isn't");
assert.equal(doc.things[1].id,"Users Guide To The Universe");
done();
})
});
})
});
it('Update works with populated arrays (gh-602)', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users)
var user1 = new User({ name: 'aphex' });
var user2 = new User({ name: 'twin' });
User.create({name:'aphex'},{name:'twin'}, function (err, u1, u2) {
assert.ifError(err);
var post = BlogPost.create({
title: 'Woot'
, fans: []
}, function (err, post) {
assert.ifError(err);
var update = { fans: [u1, u2] };
BlogPost.update({ _id: post }, update, function (err) {
assert.ifError(err);
// the original update doc should not be modified
assert.ok('fans' in update);
assert.ok(!('$set' in update));
assert.ok(update.fans[0] instanceof mongoose.Document);
assert.ok(update.fans[1] instanceof mongoose.Document);
BlogPost.findById(post, function (err, post) {
db.close();
assert.ifError(err);
assert.equal(post.fans.length,2);
assert.ok(post.fans[0] instanceof DocObjectId);
assert.ok(post.fans[1] instanceof DocObjectId);
done();
});
});
});
});
});
it('toJSON should also be called for refs (gh-675)', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefUser', users)
User.prototype._toJSON = User.prototype.toJSON;
User.prototype.toJSON = function() {
var res = this._toJSON();
res.was_in_to_json = true;
return res;
}
BlogPost.prototype._toJSON = BlogPost.prototype.toJSON;
BlogPost.prototype.toJSON = function() {
var res = this._toJSON();
res.was_in_to_json = true;
return res;
}
User.create({
name : 'Jerem'
, email : 'jerem@jolicloud.com'
}, function (err, creator) {
assert.ifError(err);
BlogPost.create({
title : 'Ping Pong'
, _creator : creator
}, function (err, post) {
assert.ifError(err);
BlogPost
.findById(post._id)
.populate('_creator')
.exec(function (err, post) {
db.close();
assert.ifError(err);
var json = post.toJSON();
assert.equal(true, json.was_in_to_json);
assert.equal(json._creator.was_in_to_json,true);
done();
});
});
});
});
it('populate should work on Buffer _ids (gh-686)', function(done){
var db = start();
var UserSchema = new Schema({
_id: Buffer
, name: String
})
var NoteSchema = new Schema({
author: { type: Buffer, ref: 'UserWithBufferId' }
, body: String
})
var User = db.model('UserWithBufferId', UserSchema, random())
var Note = db.model('NoteWithBufferId', NoteSchema, random())
var alice = new User({_id: new mongoose.Types.Buffer('YWxpY2U=', 'base64'), name: "Alice"})
alice.save(function (err) {
assert.ifError(err);
var note = new Note({author: 'alice', body: "Buy Milk"});
note.save(function (err) {
assert.ifError(err);
Note.findById(note.id).populate('author').exec(function (err, note) {
db.close();
assert.ifError(err);
assert.equal(note.body,'Buy Milk');
assert.ok(note.author);
assert.equal(note.author.name,'Alice');
done();
});
});
})
});
it('populating with custom model selection (gh-773)', function(done){
var db = start()
, BlogPost = db.model('RefBlogPost', posts)
, User = db.model('RefAlternateUser', users);
User.create({
name : 'Daniel'
, email : 'daniel.baulig@gmx.de'
}, function (err, creator) {
assert.ifError(err);
BlogPost.create({
title : 'woot'
, _creator : creator
}, function (err, post) {
assert.ifError(err);
BlogPost
.findById(post._id)
.populate('_creator', 'email', 'RefAlternateUser')
.exec(function (err, post) {
db.close();
assert.ifError(err);
assert.ok(post._creator instanceof User);
assert.equal(post._creator.isInit('name'), false);
assert.equal(post._creator.email,'daniel.baulig@gmx.de');
done();
});
});
});
})
});