summaryrefslogtreecommitdiff
path: root/node_modules/mongoose/test/model.ref.test.js
diff options
context:
space:
mode:
authorJules Laplace <jules@okfoc.us>2012-09-24 16:22:07 -0400
committerJules Laplace <jules@okfoc.us>2012-09-24 16:22:07 -0400
commit686106d544ecc3b6ffd4db2b665d3bc879a58d8c (patch)
treea5b5e50237cef70e12f0745371896e96f5f6d578 /node_modules/mongoose/test/model.ref.test.js
ok
Diffstat (limited to 'node_modules/mongoose/test/model.ref.test.js')
-rw-r--r--node_modules/mongoose/test/model.ref.test.js1528
1 files changed, 1528 insertions, 0 deletions
diff --git a/node_modules/mongoose/test/model.ref.test.js b/node_modules/mongoose/test/model.ref.test.js
new file mode 100644
index 0000000..967b6e4
--- /dev/null
+++ b/node_modules/mongoose/test/model.ref.test.js
@@ -0,0 +1,1528 @@
+
+/**
+ * Test dependencies.
+ */
+
+var start = require('./common')
+ , should = require('should')
+ , 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);
+
+/**
+ * Tests.
+ */
+
+module.exports = {
+
+ 'test populating a single reference': function () {
+ var db = start()
+ , BlogPost = db.model('RefBlogPost', posts)
+ , User = db.model('RefUser', users)
+
+ User.create({
+ name : 'Guillermo'
+ , email : 'rauchg@gmail.com'
+ }, function (err, creator) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'woot'
+ , _creator : creator
+ }, function (err, post) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .findById(post._id)
+ .populate('_creator')
+ .run(function (err, post) {
+ db.close();
+ should.strictEqual(err, null);
+
+ post._creator.should.be.an.instanceof(User);
+ post._creator.name.should.equal('Guillermo');
+ post._creator.email.should.equal('rauchg@gmail.com');
+ });
+ });
+ });
+ },
+
+ 'test an error in single reference population propagates': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'woot'
+ , _creator : creator
+ }, function (err, post) {
+ should.strictEqual(err, null);
+
+ 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')
+ .run(function (err, post) {
+ db.close();
+ err.should.be.an.instanceof(Error);
+ err.message.should.equal('woot');
+ });
+ });
+ });
+ },
+
+ 'test populating with partial fields selection': function () {
+ var db = start()
+ , BlogPost = db.model('RefBlogPost', posts)
+ , User = db.model('RefUser', users);
+
+ User.create({
+ name : 'Guillermo'
+ , email : 'rauchg@gmail.com'
+ }, function (err, creator) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'woot'
+ , _creator : creator
+ }, function (err, post) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .findById(post._id)
+ .populate('_creator', ['email'])
+ .run(function (err, post) {
+ db.close();
+ should.strictEqual(err, null);
+
+ post._creator.should.be.an.instanceof(User);
+ post._creator.isInit('name').should.be.false;
+ post._creator.email.should.equal('rauchg@gmail.com');
+ });
+ });
+ });
+ },
+
+ 'populating single oid with partial field selection and filter': function () {
+ var db = start()
+ , BlogPost = db.model('RefBlogPost', posts)
+ , User = db.model('RefUser', users);
+
+ User.create({
+ name : 'Banana'
+ , email : 'cats@example.com'
+ }, function (err, creator) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'woot'
+ , _creator : creator
+ }, function (err, post) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .findById(post._id)
+ .populate('_creator', 'email', { name: 'Peanut' })
+ .run(function (err, post) {
+ should.strictEqual(err, null);
+ should.strictEqual(post._creator, null);
+
+ BlogPost
+ .findById(post._id)
+ .populate('_creator', 'email', { name: 'Banana' })
+ .run(function (err, post) {
+ db.close();
+ should.strictEqual(err, null);
+ post._creator.should.be.an.instanceof(User);
+ post._creator.isInit('name').should.be.false;
+ post._creator.email.should.equal('cats@example.com');
+ });
+ });
+ });
+ });
+ },
+
+ 'test populating and changing a reference': function () {
+ var db = start()
+ , BlogPost = db.model('RefBlogPost', posts)
+ , User = db.model('RefUser', users);
+
+ User.create({
+ name : 'Guillermo'
+ , email : 'rauchg@gmail.com'
+ }, function (err, creator) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'woot'
+ , _creator : creator
+ }, function (err, post) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .findById(post._id)
+ .populate('_creator')
+ .run(function (err, post) {
+ should.strictEqual(err, null);
+
+ post._creator.should.be.an.instanceof(User);
+ post._creator.name.should.equal('Guillermo');
+ post._creator.email.should.equal('rauchg@gmail.com');
+
+ User.create({
+ name : 'Aaron'
+ , email : 'aaron@learnboost.com'
+ }, function (err, newCreator) {
+ should.strictEqual(err, null);
+
+ post._creator = newCreator._id;
+ post.save(function (err) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .findById(post._id)
+ .populate('_creator')
+ .run(function (err, post) {
+ db.close();
+ should.strictEqual(err, null);
+
+ post._creator.name.should.equal('Aaron');
+ post._creator.email.should.equal('aaron@learnboost.com');
+ });
+ });
+ });
+ });
+ });
+ });
+ },
+
+ 'test populating with partial fields selection and changing ref': function () {
+ var db = start()
+ , BlogPost = db.model('RefBlogPost', posts)
+ , User = db.model('RefUser', users);
+
+ User.create({
+ name : 'Guillermo'
+ , email : 'rauchg@gmail.com'
+ }, function (err, creator) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'woot'
+ , _creator : creator
+ }, function (err, post) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .findById(post._id)
+ .populate('_creator', {'name': 1})
+ .run(function (err, post) {
+ should.strictEqual(err, null);
+
+ post._creator.should.be.an.instanceof(User);
+ post._creator.name.should.equal('Guillermo');
+
+ User.create({
+ name : 'Aaron'
+ , email : 'aaron@learnboost.com'
+ }, function (err, newCreator) {
+ should.strictEqual(err, null);
+
+ post._creator = newCreator._id;
+ post.save(function (err) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .findById(post._id)
+ .populate('_creator', {email: 0})
+ .run(function (err, post) {
+ db.close();
+ should.strictEqual(err, null);
+
+ post._creator.name.should.equal('Aaron');
+ should.not.exist(post._creator.email);
+ });
+ });
+ });
+ });
+ });
+ });
+ },
+
+ 'test populating an array of references and fetching many': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ User.create({
+ name : 'Fan 2'
+ , email : 'fan2@learnboost.com'
+ }, function (err, fan2) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'Woot'
+ , fans : [fan1, fan2]
+ }, function (err, post1) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'Woot'
+ , fans : [fan2, fan1]
+ }, function (err, post2) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .find({ _id: { $in: [post1._id, post2._id ] } })
+ .populate('fans')
+ .run(function (err, blogposts) {
+ db.close();
+ should.strictEqual(err, null);
+
+ blogposts[0].fans[0].name.should.equal('Fan 1');
+ blogposts[0].fans[0].email.should.equal('fan1@learnboost.com');
+ blogposts[0].fans[1].name.should.equal('Fan 2');
+ blogposts[0].fans[1].email.should.equal('fan2@learnboost.com');
+
+ blogposts[1].fans[0].name.should.equal('Fan 2');
+ blogposts[1].fans[0].email.should.equal('fan2@learnboost.com');
+ blogposts[1].fans[1].name.should.equal('Fan 1');
+ blogposts[1].fans[1].email.should.equal('fan1@learnboost.com');
+
+ });
+ });
+ });
+ });
+ });
+ },
+
+ 'test an error in array reference population propagates': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ User.create({
+ name : 'Fan 2'
+ , email : 'fan2@learnboost.com'
+ }, function (err, fan2) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'Woot'
+ , fans : [fan1, fan2]
+ }, function (err, post1) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'Woot'
+ , fans : [fan2, fan1]
+ }, function (err, post2) {
+ should.strictEqual(err, null);
+
+ // 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')
+ .run(function (err, blogposts) {
+ db.close();
+ err.should.be.an.instanceof(Error);
+ err.message.should.equal('woot 2');
+ });
+ });
+ });
+ });
+ });
+ },
+
+ 'test populating an array of references with fields selection': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ User.create({
+ name : 'Fan 2'
+ , email : 'fan2@learnboost.com'
+ }, function (err, fan2) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'Woot'
+ , fans : [fan1, fan2]
+ }, function (err, post1) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'Woot'
+ , fans : [fan2, fan1]
+ }, function (err, post2) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .find({ _id: { $in: [post1._id, post2._id ] } })
+ .populate('fans', 'name')
+ .run(function (err, blogposts) {
+ db.close();
+ should.strictEqual(err, null);
+
+ blogposts[0].fans[0].name.should.equal('Fan 1');
+ blogposts[0].fans[0].isInit('email').should.be.false;
+ blogposts[0].fans[1].name.should.equal('Fan 2');
+ blogposts[0].fans[1].isInit('email').should.be.false;
+ should.strictEqual(blogposts[0].fans[1].email, undefined);
+
+ blogposts[1].fans[0].name.should.equal('Fan 2');
+ blogposts[1].fans[0].isInit('email').should.be.false;
+ blogposts[1].fans[1].name.should.equal('Fan 1');
+ blogposts[1].fans[1].isInit('email').should.be.false;
+ });
+ });
+ });
+ });
+ });
+ },
+
+ 'test populating an array of references and filtering': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ User.create({
+ name : 'Fan 2'
+ , email : 'fan2@learnboost.com'
+ , gender : 'female'
+ }, function (err, fan2) {
+ should.strictEqual(err, null);
+
+ User.create({
+ name : 'Fan 3'
+ , email : 'fan3@learnboost.com'
+ , gender : 'female'
+ }, function (err, fan3) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'Woot'
+ , fans : [fan1, fan2, fan3]
+ }, function (err, post1) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'Woot'
+ , fans : [fan3, fan2, fan1]
+ }, function (err, post2) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .find({ _id: { $in: [post1._id, post2._id ] } })
+ .populate('fans', '', { gender: 'female', _id: { $in: [fan2] }})
+ .run(function (err, blogposts) {
+ should.strictEqual(err, null);
+
+ blogposts[0].fans.length.should.equal(1);
+ blogposts[0].fans[0].gender.should.equal('female');
+ blogposts[0].fans[0].name.should.equal('Fan 2');
+ blogposts[0].fans[0].email.should.equal('fan2@learnboost.com');
+
+ blogposts[1].fans.length.should.equal(1);
+ blogposts[1].fans[0].gender.should.equal('female');
+ blogposts[1].fans[0].name.should.equal('Fan 2');
+ blogposts[1].fans[0].email.should.equal('fan2@learnboost.com');
+
+ BlogPost
+ .find({ _id: { $in: [post1._id, post2._id ] } })
+ .populate('fans', false, { gender: 'female' })
+ .run(function (err, blogposts) {
+ db.close();
+ should.strictEqual(err, null);
+
+ should.strictEqual(blogposts[0].fans.length, 2);
+ blogposts[0].fans[0].gender.should.equal('female');
+ blogposts[0].fans[0].name.should.equal('Fan 2');
+ blogposts[0].fans[0].email.should.equal('fan2@learnboost.com');
+ blogposts[0].fans[1].gender.should.equal('female');
+ blogposts[0].fans[1].name.should.equal('Fan 3');
+ blogposts[0].fans[1].email.should.equal('fan3@learnboost.com');
+
+ should.strictEqual(blogposts[1].fans.length, 2);
+ blogposts[1].fans[0].gender.should.equal('female');
+ blogposts[1].fans[0].name.should.equal('Fan 3');
+ blogposts[1].fans[0].email.should.equal('fan3@learnboost.com');
+ blogposts[1].fans[1].gender.should.equal('female');
+ blogposts[1].fans[1].name.should.equal('Fan 2');
+ blogposts[1].fans[1].email.should.equal('fan2@learnboost.com');
+ });
+
+ });
+ });
+ });
+ });
+ });
+ });
+ },
+
+ 'test populating an array of references and multi-filtering': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ User.create({
+ name : 'Fan 2'
+ , email : 'fan2@learnboost.com'
+ , gender : 'female'
+ }, function (err, fan2) {
+ should.strictEqual(err, null);
+
+ User.create({
+ name : 'Fan 3'
+ , email : 'fan3@learnboost.com'
+ , gender : 'female'
+ , age : 25
+ }, function (err, fan3) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'Woot'
+ , fans : [fan1, fan2, fan3]
+ }, function (err, post1) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'Woot'
+ , fans : [fan3, fan2, fan1]
+ }, function (err, post2) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .find({ _id: { $in: [post1._id, post2._id ] } })
+ .populate('fans', undefined, { _id: fan3 })
+ .run(function (err, blogposts) {
+ should.strictEqual(err, null);
+
+ blogposts[0].fans.length.should.equal(1);
+ blogposts[0].fans[0].gender.should.equal('female');
+ blogposts[0].fans[0].name.should.equal('Fan 3');
+ blogposts[0].fans[0].email.should.equal('fan3@learnboost.com');
+ should.equal(blogposts[0].fans[0].age, 25);
+
+ blogposts[1].fans.length.should.equal(1);
+ blogposts[1].fans[0].gender.should.equal('female');
+ blogposts[1].fans[0].name.should.equal('Fan 3');
+ blogposts[1].fans[0].email.should.equal('fan3@learnboost.com');
+ should.equal(blogposts[1].fans[0].age, 25);
+
+ BlogPost
+ .find({ _id: { $in: [post1._id, post2._id ] } })
+ .populate('fans', 0, { gender: 'female' })
+ .run(function (err, blogposts) {
+ db.close();
+ should.strictEqual(err, null);
+
+ blogposts[0].fans.length.should.equal(2);
+ blogposts[0].fans[0].gender.should.equal('female');
+ blogposts[0].fans[0].name.should.equal('Fan 2');
+ blogposts[0].fans[0].email.should.equal('fan2@learnboost.com');
+ blogposts[0].fans[1].gender.should.equal('female');
+ blogposts[0].fans[1].name.should.equal('Fan 3');
+ blogposts[0].fans[1].email.should.equal('fan3@learnboost.com');
+ should.equal(blogposts[0].fans[1].age, 25);
+
+ blogposts[1].fans.length.should.equal(2);
+ blogposts[1].fans[0].gender.should.equal('female');
+ blogposts[1].fans[0].name.should.equal('Fan 3');
+ blogposts[1].fans[0].email.should.equal('fan3@learnboost.com');
+ should.equal(blogposts[1].fans[0].age, 25);
+ blogposts[1].fans[1].gender.should.equal('female');
+ blogposts[1].fans[1].name.should.equal('Fan 2');
+ blogposts[1].fans[1].email.should.equal('fan2@learnboost.com');
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ },
+
+ 'test populating an array of references and multi-filtering with field selection': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ User.create({
+ name : 'Fan 2'
+ , email : 'fan2@learnboost.com'
+ , gender : 'female'
+ }, function (err, fan2) {
+ should.strictEqual(err, null);
+
+ User.create({
+ name : 'Fan 3'
+ , email : 'fan3@learnboost.com'
+ , gender : 'female'
+ , age : 25
+ }, function (err, fan3) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'Woot'
+ , fans : [fan1, fan2, fan3]
+ }, function (err, post1) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'Woot'
+ , fans : [fan3, fan2, fan1]
+ }, function (err, post2) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .find({ _id: { $in: [post1._id, post2._id ] } })
+ .populate('fans', 'name email', { gender: 'female', age: 25 })
+ .run(function (err, blogposts) {
+ db.close();
+ should.strictEqual(err, null);
+
+ should.strictEqual(blogposts[0].fans.length, 1);
+ blogposts[0].fans[0].name.should.equal('Fan 3');
+ blogposts[0].fans[0].email.should.equal('fan3@learnboost.com');
+ blogposts[0].fans[0].isInit('email').should.be.true;
+ blogposts[0].fans[0].isInit('gender').should.be.false;
+ blogposts[0].fans[0].isInit('age').should.be.false;
+
+ should.strictEqual(blogposts[1].fans.length, 1);
+ blogposts[1].fans[0].name.should.equal('Fan 3');
+ blogposts[1].fans[0].email.should.equal('fan3@learnboost.com');
+ blogposts[1].fans[0].isInit('email').should.be.true;
+ blogposts[1].fans[0].isInit('gender').should.be.false;
+ blogposts[1].fans[0].isInit('age').should.be.false;
+ });
+ });
+ });
+ });
+ });
+ });
+ },
+
+ 'test populating an array of refs, changing one, and removing one': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'Woot'
+ , fans : [fan1, fan2]
+ }, {
+ title : 'Woot'
+ , fans : [fan2, fan1]
+ }, function (err, post1, post2) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .find({ _id: { $in: [post1._id, post2._id ] } })
+ .populate('fans', ['name'])
+ .run(function (err, blogposts) {
+ should.strictEqual(err, null);
+
+ blogposts[0].fans[0].name.should.equal('Fan 1');
+ blogposts[0].fans[0].isInit('email').should.be.false;
+ blogposts[0].fans[1].name.should.equal('Fan 2');
+ blogposts[0].fans[1].isInit('email').should.be.false;
+
+ blogposts[1].fans[0].name.should.equal('Fan 2');
+ blogposts[1].fans[0].isInit('email').should.be.false;
+ blogposts[1].fans[1].name.should.equal('Fan 1');
+ blogposts[1].fans[1].isInit('email').should.be.false;
+
+ blogposts[1].fans = [fan3, fan4];
+
+ blogposts[1].save(function (err) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .findById(blogposts[1]._id, [], { populate: ['fans'] })
+ .run(function (err, post) {
+ should.strictEqual(err, null);
+
+ post.fans[0].name.should.equal('Fan 3');
+ post.fans[1].name.should.equal('Fan 4');
+
+ post.fans.splice(0, 1);
+ post.save(function (err) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .findById(post._id)
+ .populate('fans')
+ .run(function (err, post) {
+ db.close();
+ should.strictEqual(err, null);
+ post.fans.length.should.equal(1);
+ post.fans[0].name.should.equal('Fan 4');
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ },
+
+ 'test populating subdocuments': function () {
+ var db = start()
+ , BlogPost = db.model('RefBlogPost', posts)
+ , User = db.model('RefUser', users);
+
+ User.create({ name: 'User 1' }, function (err, user1) {
+ should.strictEqual(err, null);
+
+ User.create({ name: 'User 2' }, function (err, user2) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title: 'Woot'
+ , _creator: user1._id
+ , comments: [
+ { _creator: user1._id, content: 'Woot woot' }
+ , { _creator: user2._id, content: 'Wha wha' }
+ ]
+ }, function (err, post) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .findById(post._id)
+ .populate('_creator')
+ .populate('comments._creator')
+ .run(function (err, post) {
+ db.close();
+ should.strictEqual(err, null);
+
+ post._creator.name.should.equal('User 1');
+ post.comments[0]._creator.name.should.equal('User 1');
+ post.comments[1]._creator.name.should.equal('User 2');
+ });
+ });
+ });
+ });
+ },
+
+ 'test populating subdocuments partially': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ User.create({
+ name : 'User 2'
+ , email : 'user2@learnboost.com'
+ }, function (err, user2) {
+ should.strictEqual(err, null);
+
+ var post = BlogPost.create({
+ title: 'Woot'
+ , comments: [
+ { _creator: user1, content: 'Woot woot' }
+ , { _creator: user2, content: 'Wha wha' }
+ ]
+ }, function (err, post) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .findById(post._id)
+ .populate('comments._creator', ['email'])
+ .run(function (err, post) {
+ db.close();
+ should.strictEqual(err, null);
+
+ post.comments[0]._creator.email.should.equal('user1@learnboost.com');
+ post.comments[0]._creator.isInit('name').should.be.false;
+ post.comments[1]._creator.email.should.equal('user2@learnboost.com');
+ post.comments[1]._creator.isInit('name').should.be.false;
+ });
+ });
+ });
+ });
+ },
+
+ 'test populating subdocuments partially with conditions': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ User.create({
+ name : 'User 2'
+ , email : 'user2@learnboost.com'
+ }, function (err, user2) {
+ should.strictEqual(err, null);
+
+ var post = BlogPost.create({
+ title: 'Woot'
+ , comments: [
+ { _creator: user1, content: 'Woot woot' }
+ , { _creator: user2, content: 'Wha wha' }
+ ]
+ }, function (err, post) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .findById(post._id)
+ .populate('comments._creator', {'email': 1}, { name: /User/ })
+ .run(function (err, post) {
+ db.close();
+ should.strictEqual(err, null);
+
+ post.comments[0]._creator.email.should.equal('user1@learnboost.com');
+ post.comments[0]._creator.isInit('name').should.be.false;
+ post.comments[1]._creator.email.should.equal('user2@learnboost.com');
+ post.comments[1]._creator.isInit('name').should.be.false;
+ });
+ });
+ });
+ });
+ },
+
+ 'populating subdocs with invalid/missing subproperties': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ User.create({
+ name : 'T-1000'
+ , email : 'terminator1000@learnboost.com'
+ }, function (err, user2) {
+ should.strictEqual(err, null);
+
+ var post = BlogPost.create({
+ title: 'Woot'
+ , comments: [
+ { _creator: null, content: 'Woot woot' }
+ , { _creator: user2, content: 'Wha wha' }
+ ]
+ }, function (err, post) {
+ should.strictEqual(err, null);
+
+ // invalid subprop
+ BlogPost
+ .findById(post._id)
+ .populate('comments._idontexist', 'email')
+ .run(function (err, post) {
+ should.strictEqual(err, null);
+ should.exist(post);
+ post.comments.length.should.equal(2);
+ should.strictEqual(post.comments[0]._creator, null);
+ post.comments[1]._creator.toString().should.equal(user2.id);
+
+ // subprop is null in a doc
+ BlogPost
+ .findById(post._id)
+ .populate('comments._creator', 'email')
+ .run(function (err, post) {
+ db.close();
+ should.strictEqual(err, null);
+
+ should.exist(post);
+ post.comments.length.should.equal(2);
+ should.strictEqual(post.comments[0]._creator, null);
+ should.strictEqual(post.comments[0].content, 'Woot woot');
+ post.comments[1]._creator.email.should.equal('terminator1000@learnboost.com');
+ post.comments[1]._creator.isInit('name').should.be.false;
+ post.comments[1].content.should.equal('Wha wha');
+ });
+ });
+ });
+ });
+ });
+ },
+
+ // gh-481
+ 'test populating subdocuments partially with empty array': function (beforeExit) {
+ var db = start()
+ , BlogPost = db.model('RefBlogPost', posts)
+ , worked = false;
+
+ var post = BlogPost.create({
+ title: 'Woot'
+ , comments: [] // EMPTY ARRAY
+ }, function (err, post) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .findById(post._id)
+ .populate('comments._creator', ['email'])
+ .run(function (err, returned) {
+ db.close();
+ worked = true;
+ should.strictEqual(err, null);
+ returned.id.should.equal(post.id);
+ });
+ });
+
+ beforeExit(function () {
+ worked.should.be.true;
+ });
+ },
+
+ 'populating subdocuments with array including nulls': function () {
+ var db = start()
+ , BlogPost = db.model('RefBlogPost', posts)
+ , User = db.model('RefUser', users)
+
+ var user = new User({ name: 'hans zimmer' });
+ user.save(function (err) {
+ should.strictEqual(err, null);
+
+ var post = BlogPost.create({
+ title: 'Woot'
+ , fans: []
+ }, function (err, post) {
+ should.strictEqual(err, null);
+
+ // shove some uncasted vals
+ BlogPost.collection.update({ _id: post._id }, { $set: { fans: [null, undefined, user.id, null] } }, function (err) {
+ should.strictEqual(err, undefined);
+
+ BlogPost
+ .findById(post._id)
+ .populate('fans', ['name'])
+ .run(function (err, returned) {
+ db.close();
+ should.strictEqual(err, null);
+ returned.id.should.equal(post.id);
+ returned.fans.length.should.equal(1);
+ });
+ })
+ });
+ });
+ },
+
+ 'populating more than one array at a time': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ 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) {
+ should.strictEqual(err, null);
+
+ M.where('_id').in([post1, post2])
+ .populate('fans', 'name', { gender: 'female' })
+ .populate('users', 'name', { gender: 'male' })
+ .populate('comments._creator', ['email'], { name: null })
+ .run(function (err, posts) {
+ db.close();
+ should.strictEqual(err, null);
+
+ should.exist(posts);
+ posts.length.should.equal(2);
+ var p1 = posts[0];
+ var p2 = posts[1];
+ should.strictEqual(p1.fans.length, 0);
+ should.strictEqual(p2.fans.length, 1);
+ p2.fans[0].name.should.equal('Fan 2');
+ p2.fans[0].isInit('email').should.be.false;
+ p2.fans[0].isInit('gender').should.be.false;
+ p1.comments.length.should.equal(2);
+ p2.comments.length.should.equal(2);
+ should.exist(p1.comments[0]._creator.email);
+ should.not.exist(p2.comments[0]._creator);
+ p1.comments[0]._creator.email.should.equal('fan1@learnboost.com');
+ p2.comments[1]._creator.email.should.equal('fan1@learnboost.com');
+ p1.comments[0]._creator.isInit('name').should.be.false;
+ p2.comments[1]._creator.isInit('name').should.be.false;
+ p1.comments[0].content.should.equal('bejeah!');
+ p2.comments[1].content.should.equal('world');
+ should.not.exist(p1.comments[1]._creator);
+ should.not.exist(p2.comments[0]._creator);
+ p1.comments[1].content.should.equal('chickfila');
+ p2.comments[0].content.should.equal('hello');
+ });
+ });
+ });
+ },
+
+ 'populating multiple children of a sub-array at a time': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'woot'
+ }, {
+ title : 'yay'
+ }, function (err, post1, post2) {
+ should.strictEqual(err, null);
+ M.create({
+ kids: [
+ { user: fan1, post: post1, y: 5 }
+ , { user: fan2, post: post2, y: 8 }
+ ]
+ , x: 4
+ }, function (err, m1) {
+ should.strictEqual(err, null);
+
+ M.findById(m1)
+ .populate('kids.user', ["name"])
+ .populate('kids.post', ["title"], { title: "woot" })
+ .run(function (err, o) {
+ db.close();
+ should.strictEqual(err, null);
+ should.strictEqual(o.kids.length, 2);
+ var k1 = o.kids[0];
+ var k2 = o.kids[1];
+ should.strictEqual(true, !k2.post);
+ should.strictEqual(k1.user.name, "Fan 1");
+ should.strictEqual(k1.user.email, undefined);
+ should.strictEqual(k1.post.title, "woot");
+ should.strictEqual(k2.user.name, "Fan 2");
+ });
+ });
+ });
+ });
+ },
+
+ 'passing sort options to the populate method': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ P.create({ fans: [fan2, fan3, fan1] }, function (err, post) {
+ should.strictEqual(err, null);
+
+ P.findById(post)
+ .populate('fans', null, null, { sort: 'name' })
+ .run(function (err, post) {
+ should.strictEqual(err, null);
+
+ post.fans.length.should.equal(3);
+ post.fans[0].name.should.equal('aaron');
+ post.fans[1].name.should.equal('fan2');
+ post.fans[2].name.should.equal('someone else');
+
+ P.findById(post)
+ .populate('fans', 'name', null, { sort: [['name', -1]] })
+ .run(function (err, post) {
+ should.strictEqual(err, null);
+
+ post.fans.length.should.equal(3);
+ post.fans[2].name.should.equal('aaron');
+ should.strictEqual(undefined, post.fans[2].age)
+ post.fans[1].name.should.equal('fan2');
+ should.strictEqual(undefined, post.fans[1].age)
+ post.fans[0].name.should.equal('someone else');
+ should.strictEqual(undefined, post.fans[0].age)
+
+ P.findById(post)
+ .populate('fans', 'age', { age: { $gt: 3 }}, { sort: [['name', 'desc']] })
+ .run(function (err, post) {
+ db.close();
+ should.strictEqual(err, null);
+
+ post.fans.length.should.equal(2);
+ post.fans[1].age.valueOf().should.equal(10);
+ post.fans[0].age.valueOf().should.equal(8);
+ });
+ });
+ });
+ });
+ });
+ },
+
+ 'refs should cast to ObjectId from hexstrings': function () {
+ var BP = mongoose.model('RefBlogPost', BlogPost);
+ var bp = new BP;
+ bp._creator = new DocObjectId().toString();
+ bp._creator.should.be.an.instanceof(DocObjectId);
+ bp.set('_creator', new DocObjectId().toString());
+ bp._creator.should.be.an.instanceof(DocObjectId);
+ },
+
+ 'populate should work on String _ids': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ var note = new Note({author: 'alice', body: "Buy Milk"});
+ note.save(function (err) {
+ should.strictEqual(err, null);
+
+ Note.findById(note.id).populate('author').run(function (err, note) {
+ db.close();
+ should.strictEqual(err, null);
+ note.body.should.equal('Buy Milk');
+ should.exist(note.author);
+ note.author.name.should.equal('Alice');
+ });
+ });
+ })
+ },
+
+ 'populate should work on Number _ids': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ var note = new Note({author: 2359, body: "Buy Milk"});
+ note.save(function (err) {
+ should.strictEqual(err, null);
+
+ Note.findById(note.id).populate('author').run(function (err, note) {
+ db.close();
+ should.strictEqual(err, null);
+ note.body.should.equal('Buy Milk');
+ should.exist(note.author);
+ note.author.name.should.equal('Alice');
+ });
+ });
+ })
+ },
+
+ // gh-577
+ 'required works on ref fields': function () {
+ 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) {
+ should.strictEqual(null, err);
+ if (--pending) return;
+
+ var comment = new Comment({
+ text: 'test'
+ });
+
+ comment.save(function (err) {
+ should.equal('Validation failed', err && err.message);
+ err.errors.should.have.property('num');
+ err.errors.should.have.property('str');
+ err.errors.should.have.property('user');
+ err.errors.num.type.should.equal('required');
+ err.errors.str.type.should.equal('required');
+ err.errors.user.type.should.equal('required');
+
+ comment.user = user;
+ comment.num = 1995;
+ comment.str = 'my string';
+
+ comment.save(function (err, comment) {
+ should.strictEqual(null, err);
+
+ Comment
+ .findById(comment.id)
+ .populate('user')
+ .populate('num')
+ .populate('str')
+ .run(function (err, comment) {
+ should.strictEqual(err, null);
+
+ comment.set({text: 'test2'});
+
+ comment.save(function (err, comment) {
+ db.close();
+ should.strictEqual(err, null);
+ });
+ });
+ });
+ });
+ }
+ },
+
+ 'populate works with schemas with both id and _id defined': function () {
+ 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) {
+ should.strictEqual(null, err);
+
+ var m2 = new M2({ things: [a, b]});
+ m2.save(function (err) {
+ should.strictEqual(null, err);
+ M2.findById(m2).populate('things').run(function (err, doc) {
+ db.close();
+ should.strictEqual(null, err);
+ doc.things.length.should.equal(2);
+ doc.things[0].id.should.equal("The Tiger That Isn't");
+ doc.things[1].id.should.equal("Users Guide To The Universe");
+ })
+ });
+ })
+ },
+
+ // gh-602
+ 'Update works with populated arrays': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ var post = BlogPost.create({
+ title: 'Woot'
+ , fans: []
+ }, function (err, post) {
+ should.strictEqual(err, null);
+
+ var update = { fans: [u1, u2] };
+ BlogPost.update({ _id: post }, update, function (err) {
+ should.strictEqual(err, null);
+
+ // the original update doc should not be modified
+ ;('fans' in update).should.be.true;
+ ;('$set' in update).should.be.false;
+ update.fans[0].should.be.instanceof(mongoose.Document);
+ update.fans[1].should.be.instanceof(mongoose.Document);
+
+ BlogPost.findById(post, function (err, post) {
+ db.close();
+ should.strictEqual(err, null);
+ post.fans.length.should.equal(2);
+ post.fans[0].should.be.instanceof(DocObjectId);
+ post.fans[1].should.be.instanceof(DocObjectId);
+ });
+ });
+ });
+ });
+ },
+
+ // gh-675
+ 'toJSON should also be called for refs': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ BlogPost.create({
+ title : 'Ping Pong'
+ , _creator : creator
+ }, function (err, post) {
+ should.strictEqual(err, null);
+
+ BlogPost
+ .findById(post._id)
+ .populate('_creator')
+ .run(function (err, post) {
+ db.close();
+ should.strictEqual(err, null);
+
+ var json = post.toJSON();
+ json.was_in_to_json.should.equal(true);
+ json._creator.was_in_to_json.should.equal(true);
+ });
+ });
+ });
+ },
+
+ // gh-686
+ 'populate should work on Buffer _ids': function () {
+ 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) {
+ should.strictEqual(err, null);
+
+ var note = new Note({author: 'alice', body: "Buy Milk"});
+ note.save(function (err) {
+ should.strictEqual(err, null);
+
+ Note.findById(note.id).populate('author').run(function (err, note) {
+ db.close();
+ should.strictEqual(err, null);
+ note.body.should.equal('Buy Milk');
+ should.exist(note.author);
+ note.author.name.should.equal('Alice');
+ });
+ });
+ })
+ }
+}; \ No newline at end of file