summaryrefslogtreecommitdiff
path: root/node_modules/mongoose/test/document.test.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/mongoose/test/document.test.js')
-rw-r--r--node_modules/mongoose/test/document.test.js912
1 files changed, 912 insertions, 0 deletions
diff --git a/node_modules/mongoose/test/document.test.js b/node_modules/mongoose/test/document.test.js
new file mode 100644
index 0000000..7c1b244
--- /dev/null
+++ b/node_modules/mongoose/test/document.test.js
@@ -0,0 +1,912 @@
+
+/**
+ * Module dependencies.
+ */
+
+var start = require('./common')
+ , should = require('should')
+ , mongoose = start.mongoose
+ , Schema = mongoose.Schema
+ , ObjectId = Schema.ObjectId
+ , Document = require('../lib/document')
+ , DocumentObjectId = mongoose.Types.ObjectId;
+
+/**
+ * Test Document constructor.
+ */
+
+function TestDocument () {
+ Document.apply(this, arguments);
+};
+
+/**
+ * Inherits from Document.
+ */
+
+TestDocument.prototype.__proto__ = Document.prototype;
+
+/**
+ * Set a dummy schema to simulate compilation.
+ */
+
+var em = new Schema({ title: String, body: String });
+var schema = TestDocument.prototype.schema = new Schema({
+ test : String
+ , oids : [ObjectId]
+ , numbers : [Number]
+ , nested : {
+ age : Number
+ , cool : ObjectId
+ , deep : { x: String }
+ , path : String
+ , setr : String
+ }
+ , nested2 : {
+ nested: String
+ , yup : {
+ nested : Boolean
+ , yup : String
+ , age : Number
+ }
+ }
+ , em: [em]
+});
+
+schema.virtual('nested.agePlus2').get(function (v) {
+ return this.nested.age + 2;
+});
+schema.virtual('nested.setAge').set(function (v) {
+ this.nested.age = v;
+});
+schema.path('nested.path').get(function (v) {
+ return this.nested.age + (v ? v : '');
+});
+schema.path('nested.setr').set(function (v) {
+ return v + ' setter';
+});
+
+/**
+ * Method subject to hooks. Simply fires the callback once the hooks are
+ * executed.
+ */
+
+TestDocument.prototype.hooksTest = function(fn){
+ fn(null, arguments);
+};
+
+/**
+ * Test.
+ */
+
+module.exports = {
+ 'test shortcut getters': function(){
+ var doc = new TestDocument();
+ doc.init({
+ test : 'test'
+ , oids : []
+ , nested : {
+ age : 5
+ , cool : DocumentObjectId.fromString('4c6c2d6240ced95d0e00003c')
+ , path : 'my path'
+ }
+ });
+
+ doc.test.should.eql('test');
+ doc.oids.should.be.an.instanceof(Array);
+ (doc.nested.age == 5).should.be.true;
+ DocumentObjectId.toString(doc.nested.cool).should.eql('4c6c2d6240ced95d0e00003c');
+ doc.nested.agePlus2.should.eql(7);
+ doc.nested.path.should.eql('5my path');
+ doc.nested.setAge = 10;
+ (doc.nested.age == 10).should.be.true;
+ doc.nested.setr = 'set it';
+ doc.getValue('nested.setr').should.eql('set it setter');
+
+ var doc2 = new TestDocument();
+ doc2.init({
+ test : 'toop'
+ , oids : []
+ , nested : {
+ age : 2
+ , cool : DocumentObjectId.fromString('4cf70857337498f95900001c')
+ , deep : { x: 'yay' }
+ }
+ });
+
+ doc2.test.should.eql('toop');
+ doc2.oids.should.be.an.instanceof(Array);
+ (doc2.nested.age == 2).should.be.true;
+
+ // GH-366
+ should.strictEqual(doc2.nested.bonk, undefined);
+ should.strictEqual(doc2.nested.nested, undefined);
+ should.strictEqual(doc2.nested.test, undefined);
+ should.strictEqual(doc2.nested.age.test, undefined);
+ should.strictEqual(doc2.nested.age.nested, undefined);
+ should.strictEqual(doc2.oids.nested, undefined);
+ should.strictEqual(doc2.nested.deep.x, 'yay');
+ should.strictEqual(doc2.nested.deep.nested, undefined);
+ should.strictEqual(doc2.nested.deep.cool, undefined);
+ should.strictEqual(doc2.nested2.yup.nested, undefined);
+ should.strictEqual(doc2.nested2.yup.nested2, undefined);
+ should.strictEqual(doc2.nested2.yup.yup, undefined);
+ should.strictEqual(doc2.nested2.yup.age, undefined);
+ doc2.nested2.yup.should.be.a('object');
+
+ doc2.nested2.yup = {
+ age: 150
+ , yup: "Yesiree"
+ , nested: true
+ };
+
+ should.strictEqual(doc2.nested2.nested, undefined);
+ should.strictEqual(doc2.nested2.yup.nested, true);
+ should.strictEqual(doc2.nested2.yup.yup, "Yesiree");
+ (doc2.nested2.yup.age == 150).should.be.true;
+ doc2.nested2.nested = "y";
+ should.strictEqual(doc2.nested2.nested, "y");
+ should.strictEqual(doc2.nested2.yup.nested, true);
+ should.strictEqual(doc2.nested2.yup.yup, "Yesiree");
+ (doc2.nested2.yup.age == 150).should.be.true;
+
+ DocumentObjectId.toString(doc2.nested.cool).should.eql('4cf70857337498f95900001c');
+
+ doc.oids.should.not.equal(doc2.oids);
+ },
+
+ 'test shortcut setters': function () {
+ var doc = new TestDocument();
+
+ doc.init({
+ test : 'Test'
+ , nested : {
+ age : 5
+ }
+ });
+
+ doc.isModified('test').should.be.false;
+ doc.test = 'Woot';
+ doc.test.should.eql('Woot');
+ doc.isModified('test').should.be.true;
+
+ doc.isModified('nested.age').should.be.false;
+ doc.nested.age = 2;
+ (doc.nested.age == 2).should.be.true;
+ doc.isModified('nested.age').should.be.true;
+ },
+
+ 'test accessor of id': function () {
+ var doc = new TestDocument();
+ doc._id.should.be.an.instanceof(DocumentObjectId);
+ },
+
+ 'test shortcut of id hexString': function () {
+ var doc = new TestDocument()
+ , _id = doc._id.toString();
+ doc.id.should.be.a('string');
+ },
+
+ 'test toObject clone': function(){
+ var doc = new TestDocument();
+ doc.init({
+ test : 'test'
+ , oids : []
+ , nested : {
+ age : 5
+ , cool : new DocumentObjectId
+ }
+ });
+
+ var copy = doc.toObject();
+
+ copy.test._marked = true;
+ copy.nested._marked = true;
+ copy.nested.age._marked = true;
+ copy.nested.cool._marked = true;
+
+ should.strictEqual(doc._doc.test._marked, undefined);
+ should.strictEqual(doc._doc.nested._marked, undefined);
+ should.strictEqual(doc._doc.nested.age._marked, undefined);
+ should.strictEqual(doc._doc.nested.cool._marked, undefined);
+ },
+
+ 'toObject options': function () {
+ var doc = new TestDocument();
+
+ doc.init({
+ test : 'test'
+ , oids : []
+ , nested : {
+ age : 5
+ , cool : DocumentObjectId.fromString('4c6c2d6240ced95d0e00003c')
+ , path : 'my path'
+ }
+ });
+
+ var clone = doc.toObject({ getters: true, virtuals: false });
+
+ clone.test.should.eql('test');
+ clone.oids.should.be.an.instanceof(Array);
+ (clone.nested.age == 5).should.be.true;
+ DocumentObjectId.toString(clone.nested.cool).should.eql('4c6c2d6240ced95d0e00003c');
+ clone.nested.path.should.eql('5my path');
+ should.equal(undefined, clone.nested.agePlus2);
+
+ clone = doc.toObject({ virtuals: true });
+
+ clone.test.should.eql('test');
+ clone.oids.should.be.an.instanceof(Array);
+ (clone.nested.age == 5).should.be.true;
+ DocumentObjectId.toString(clone.nested.cool).should.eql('4c6c2d6240ced95d0e00003c');
+ clone.nested.path.should.eql('my path');
+ clone.nested.agePlus2.should.eql(7);
+
+ clone = doc.toObject({ getters: true });
+
+ clone.test.should.eql('test');
+ clone.oids.should.be.an.instanceof(Array);
+ (clone.nested.age == 5).should.be.true;
+ DocumentObjectId.toString(clone.nested.cool).should.eql('4c6c2d6240ced95d0e00003c');
+ clone.nested.path.should.eql('5my path');
+ clone.nested.agePlus2.should.eql(7);
+ },
+
+ 'test hooks system': function(beforeExit){
+ var doc = new TestDocument()
+ , steps = 0
+ , awaiting = 0
+ , called = false;
+
+ // serial
+ doc.pre('hooksTest', function(next){
+ steps++;
+ setTimeout(function(){
+ // make sure next step hasn't executed yet
+ steps.should.eql(1);
+ next();
+ }, 50);
+ });
+
+ doc.pre('hooksTest', function(next){
+ steps++;
+ next();
+ });
+
+ // parallel
+ doc.pre('hooksTest', true, function(next, done){
+ steps++;
+ steps.should.eql(3);
+ setTimeout(function(){
+ steps.should.eql(4);
+ }, 10);
+ setTimeout(function(){
+ steps++;
+ done();
+ }, 110);
+ next();
+ });
+
+ doc.pre('hooksTest', true, function(next, done){
+ steps++;
+ setTimeout(function(){
+ steps.should.eql(4);
+ }, 10);
+ setTimeout(function(){
+ steps++;
+ done();
+ }, 110);
+ next();
+ });
+
+ doc.hooksTest(function(err){
+ should.strictEqual(err, null);
+ steps++;
+ called = true;
+ });
+
+ beforeExit(function(){
+ steps.should.eql(7);
+ called.should.be.true;
+ });
+ },
+
+ 'test that calling next twice doesnt break': function(beforeExit){
+ var doc = new TestDocument()
+ , steps = 0
+ , called = false;
+
+ doc.pre('hooksTest', function(next){
+ steps++;
+ next();
+ next();
+ });
+
+ doc.pre('hooksTest', function(next){
+ steps++;
+ next();
+ });
+
+ doc.hooksTest(function(err){
+ should.strictEqual(err, null);
+ steps++;
+ called = true;
+ });
+
+ beforeExit(function(){
+ steps.should.eql(3);
+ called.should.be.true;
+ });
+ },
+
+ 'test that calling done twice doesnt break': function(beforeExit){
+ var doc = new TestDocument()
+ , steps = 0
+ , called = false;
+
+ doc.pre('hooksTest', true, function(next, done){
+ steps++;
+ next();
+ done();
+ done();
+ });
+
+ doc.pre('hooksTest', true, function(next, done){
+ steps++;
+ next();
+ done();
+ done();
+ });
+
+ doc.hooksTest(function(err){
+ should.strictEqual(err, null);
+ steps++;
+ called = true;
+ });
+
+ beforeExit(function(){
+ steps.should.eql(3);
+ called.should.be.true;
+ });
+ },
+
+ 'test that calling done twice on the same doesnt mean completion':
+ function(beforeExit){
+ var doc = new TestDocument()
+ , steps = 0
+ , called = false;
+
+ doc.pre('hooksTest', true, function(next, done){
+ steps++;
+ next();
+ done();
+ done();
+ });
+
+ doc.pre('hooksTest', true, function(next, done){
+ steps++;
+ next();
+ });
+
+ doc.hooksTest(function(err){
+ should.strictEqual(err, null);
+ called = true;
+ });
+
+ beforeExit(function(){
+ steps.should.eql(2);
+ called.should.be.false;
+ });
+ },
+
+ 'test hooks system errors from a serial hook': function(beforeExit){
+ var doc = new TestDocument()
+ , steps = 0
+ , called = false;
+
+ doc.pre('hooksTest', function(next){
+ steps++;
+ next();
+ });
+
+ doc.pre('hooksTest', function(next){
+ steps++;
+ next(new Error);
+ });
+
+ doc.pre('hooksTest', function(next){
+ steps++;
+ });
+
+ doc.hooksTest(function(err){
+ err.should.be.an.instanceof(Error);
+ steps++;
+ called = true;
+ });
+
+ beforeExit(function(){
+ steps.should.eql(3);
+ called.should.be.true;
+ });
+ },
+
+ 'test hooks system erros from last serial hook': function(beforeExit){
+ var doc = new TestDocument()
+ , called = false;
+
+ doc.pre('hooksTest', function(next){
+ next(new Error());
+ });
+
+ doc.hooksTest(function(err){
+ err.should.be.an.instanceof(Error);
+ called = true;
+ });
+
+ beforeExit(function(){
+ called.should.be.true;
+ });
+ },
+
+ 'test mutating incoming args via middleware': function (beforeExit) {
+ var doc = new TestDocument();
+
+ doc.pre('set', function(next, path, val){
+ next(path, 'altered-' + val);
+ });
+
+ doc.set('test', 'me');
+
+ beforeExit(function(){
+ doc.test.should.equal('altered-me');
+ });
+ },
+
+ 'test hooks system errors from a parallel hook': function(beforeExit){
+ var doc = new TestDocument()
+ , steps = 0
+ , called = false;
+
+ doc.pre('hooksTest', true, function(next, done){
+ steps++;
+ next();
+ done();
+ });
+
+ doc.pre('hooksTest', true, function(next, done){
+ steps++;
+ next();
+ done();
+ });
+
+ doc.pre('hooksTest', true, function(next, done){
+ steps++;
+ next();
+ done(new Error);
+ });
+
+ doc.hooksTest(function(err){
+ err.should.be.an.instanceof(Error);
+ steps++;
+ called = true;
+ });
+
+ beforeExit(function(){
+ steps.should.eql(4);
+ called.should.be.true;
+ });
+ },
+
+ 'test that its not necessary to call the last next in the parallel chain':
+ function(beforeExit){
+ var doc = new TestDocument()
+ , steps = 0
+ , called = false;
+
+ doc.pre('hooksTest', function(next, done){
+ next();
+ done();
+ });
+
+ doc.pre('hooksTest', function(next, done){
+ done();
+ });
+
+ doc.hooksTest(function(){
+ called = true;
+ });
+
+ beforeExit(function(){
+ called.should.be.true;
+ });
+ },
+
+ 'test passing two arguments to a method subject to hooks and return value':
+ function (beforeExit) {
+ var doc = new TestDocument()
+ , called = false;
+
+ doc.pre('hooksTest', function (next) {
+ next();
+ });
+
+ doc.hooksTest(function (err, args) {
+ args.should.have.length(2);
+ args[1].should.eql('test');
+ called = true;
+ }, 'test')
+
+ beforeExit(function () {
+ called.should.be.true;
+ });
+ },
+
+ // gh-746
+ 'hooking set works with document arrays': function () {
+ var db = start();
+
+ var child = new Schema({ text: String });
+
+ child.pre('set', function (next, path, value, type) {
+ next(path, value, type);
+ });
+
+ var schema = new Schema({
+ name: String
+ , e: [child]
+ });
+
+ var S = db.model('docArrayWithHookedSet', schema);
+
+ var s = new S({ name: "test" });
+ s.e = [{ text: 'hi' }];
+ s.save(function (err) {
+ db.close();
+ should.strictEqual(null, err);
+ });
+ },
+
+ 'test jsonifying an object': function () {
+ var doc = new TestDocument({ test: 'woot' })
+ , oidString = DocumentObjectId.toString(doc._id);
+
+ // convert to json string
+ var json = JSON.stringify(doc);
+
+ // parse again
+ var obj = JSON.parse(json);
+
+ obj.test.should.eql('woot');
+ obj._id.should.eql(oidString);
+ },
+
+ 'toObject should not set undefined values to null': function () {
+ var doc = new TestDocument()
+ , obj = doc.toObject();
+
+ delete obj._id;
+ obj.should.eql({ numbers: [], oids: [], em: [] });
+ },
+
+ // GH-209
+ 'MongooseErrors should be instances of Error': function () {
+ var MongooseError = require('../lib/error')
+ , err = new MongooseError("Some message");
+ err.should.be.an.instanceof(Error);
+ },
+ 'ValidationErrors should be instances of Error': function () {
+ var ValidationError = Document.ValidationError
+ , err = new ValidationError(new TestDocument);
+ err.should.be.an.instanceof(Error);
+ },
+
+ 'methods on embedded docs should work': function () {
+ var db = start()
+ , ESchema = new Schema({ name: String })
+
+ ESchema.methods.test = function () {
+ return this.name + ' butter';
+ }
+ ESchema.statics.ten = function () {
+ return 10;
+ }
+
+ var E = db.model('EmbeddedMethodsAndStaticsE', ESchema);
+ var PSchema = new Schema({ embed: [ESchema] });
+ var P = db.model('EmbeddedMethodsAndStaticsP', PSchema);
+
+ var p = new P({ embed: [{name: 'peanut'}] });
+ should.equal('function', typeof p.embed[0].test);
+ should.equal('function', typeof E.ten);
+ p.embed[0].test().should.equal('peanut butter');
+ E.ten().should.equal(10);
+
+ // test push casting
+ p = new P;
+ p.embed.push({name: 'apple'});
+ should.equal('function', typeof p.embed[0].test);
+ should.equal('function', typeof E.ten);
+ p.embed[0].test().should.equal('apple butter');
+
+ db.close();
+ },
+
+ 'setting a positional path does not cast value to array': function () {
+ var doc = new TestDocument;
+ doc.init({ numbers: [1,3] });
+ doc.numbers[0].should.eql(1);
+ doc.numbers[1].valueOf().should.eql(3);
+ doc.set('numbers.1', 2);
+ doc.numbers[0].should.eql(1);
+ doc.numbers[1].valueOf().should.eql(2);
+ },
+
+ 'no maxListeners warning should occur': function () {
+ var db = start();
+
+ var traced = false;
+ var trace = console.trace;
+
+ console.trace = function () {
+ traced = true;
+ console.trace = trace;
+ }
+
+ var schema = new Schema({
+ title: String
+ , embed1: [new Schema({name:String})]
+ , embed2: [new Schema({name:String})]
+ , embed3: [new Schema({name:String})]
+ , embed4: [new Schema({name:String})]
+ , embed5: [new Schema({name:String})]
+ , embed6: [new Schema({name:String})]
+ , embed7: [new Schema({name:String})]
+ , embed8: [new Schema({name:String})]
+ , embed9: [new Schema({name:String})]
+ , embed10: [new Schema({name:String})]
+ , embed11: [new Schema({name:String})]
+ });
+
+ var S = db.model('noMaxListeners', schema);
+
+ var s = new S({ title: "test" });
+ db.close();
+ traced.should.be.false
+ },
+
+ 'isSelected': function () {
+ var doc = new TestDocument();
+
+ doc.init({
+ test : 'test'
+ , numbers : [4,5,6,7]
+ , nested : {
+ age : 5
+ , cool : DocumentObjectId.fromString('4c6c2d6240ced95d0e00003c')
+ , path : 'my path'
+ , deep : { x: 'a string' }
+ }
+ , notapath: 'i am not in the schema'
+ , em: [{ title: 'gocars' }]
+ });
+
+ doc.isSelected('_id').should.be.true;
+ doc.isSelected('test').should.be.true;
+ doc.isSelected('numbers').should.be.true;
+ doc.isSelected('oids').should.be.true; // even if no data
+ doc.isSelected('nested').should.be.true;
+ doc.isSelected('nested.age').should.be.true;
+ doc.isSelected('nested.cool').should.be.true;
+ doc.isSelected('nested.path').should.be.true;
+ doc.isSelected('nested.deep').should.be.true;
+ doc.isSelected('nested.nope').should.be.true; // not a path
+ doc.isSelected('nested.deep.x').should.be.true;
+ doc.isSelected('nested.deep.x.no').should.be.true;
+ doc.isSelected('nested.deep.y').should.be.true; // not a path
+ doc.isSelected('noway').should.be.true; // not a path
+ doc.isSelected('notapath').should.be.true; // not a path but in the _doc
+ doc.isSelected('em').should.be.true;
+ doc.isSelected('em.title').should.be.true;
+ doc.isSelected('em.body').should.be.true;
+ doc.isSelected('em.nonpath').should.be.true; // not a path
+
+ var selection = {
+ 'test': 1
+ , 'numbers': 1
+ , 'nested.deep': 1
+ , 'oids': 1
+ }
+
+ doc = new TestDocument(undefined, selection);
+
+ doc.init({
+ test : 'test'
+ , numbers : [4,5,6,7]
+ , nested : {
+ deep : { x: 'a string' }
+ }
+ });
+
+ doc.isSelected('_id').should.be.true;
+ doc.isSelected('test').should.be.true;
+ doc.isSelected('numbers').should.be.true;
+ doc.isSelected('oids').should.be.true; // even if no data
+ doc.isSelected('nested').should.be.true;
+ doc.isSelected('nested.age').should.be.false;
+ doc.isSelected('nested.cool').should.be.false;
+ doc.isSelected('nested.path').should.be.false;
+ doc.isSelected('nested.deep').should.be.true;
+ doc.isSelected('nested.nope').should.be.false;
+ doc.isSelected('nested.deep.x').should.be.true;
+ doc.isSelected('nested.deep.x.no').should.be.true;
+ doc.isSelected('nested.deep.y').should.be.true;
+ doc.isSelected('noway').should.be.false;
+ doc.isSelected('notapath').should.be.false;
+ doc.isSelected('em').should.be.false;
+ doc.isSelected('em.title').should.be.false;
+ doc.isSelected('em.body').should.be.false;
+ doc.isSelected('em.nonpath').should.be.false;
+
+ var selection = {
+ 'em.title': 1
+ }
+
+ doc = new TestDocument(undefined, selection);
+
+ doc.init({
+ em: [{ title: 'one' }]
+ });
+
+ doc.isSelected('_id').should.be.true;
+ doc.isSelected('test').should.be.false;
+ doc.isSelected('numbers').should.be.false;
+ doc.isSelected('oids').should.be.false;
+ doc.isSelected('nested').should.be.false;
+ doc.isSelected('nested.age').should.be.false;
+ doc.isSelected('nested.cool').should.be.false;
+ doc.isSelected('nested.path').should.be.false;
+ doc.isSelected('nested.deep').should.be.false;
+ doc.isSelected('nested.nope').should.be.false;
+ doc.isSelected('nested.deep.x').should.be.false;
+ doc.isSelected('nested.deep.x.no').should.be.false;
+ doc.isSelected('nested.deep.y').should.be.false;
+ doc.isSelected('noway').should.be.false;
+ doc.isSelected('notapath').should.be.false;
+ doc.isSelected('em').should.be.true;
+ doc.isSelected('em.title').should.be.true;
+ doc.isSelected('em.body').should.be.false;
+ doc.isSelected('em.nonpath').should.be.false;
+
+ var selection = {
+ 'em': 0
+ }
+
+ doc = new TestDocument(undefined, selection);
+ doc.init({
+ test : 'test'
+ , numbers : [4,5,6,7]
+ , nested : {
+ age : 5
+ , cool : DocumentObjectId.fromString('4c6c2d6240ced95d0e00003c')
+ , path : 'my path'
+ , deep : { x: 'a string' }
+ }
+ , notapath: 'i am not in the schema'
+ });
+
+ doc.isSelected('_id').should.be.true;
+ doc.isSelected('test').should.be.true;
+ doc.isSelected('numbers').should.be.true;
+ doc.isSelected('oids').should.be.true;
+ doc.isSelected('nested').should.be.true;
+ doc.isSelected('nested.age').should.be.true;
+ doc.isSelected('nested.cool').should.be.true;
+ doc.isSelected('nested.path').should.be.true;
+ doc.isSelected('nested.deep').should.be.true;
+ doc.isSelected('nested.nope').should.be.true;
+ doc.isSelected('nested.deep.x').should.be.true;
+ doc.isSelected('nested.deep.x.no').should.be.true;
+ doc.isSelected('nested.deep.y').should.be.true;
+ doc.isSelected('noway').should.be.true;
+ doc.isSelected('notapath').should.be.true;
+ doc.isSelected('em').should.be.false;
+ doc.isSelected('em.title').should.be.false;
+ doc.isSelected('em.body').should.be.false;
+ doc.isSelected('em.nonpath').should.be.false;
+
+ var selection = {
+ '_id': 0
+ }
+
+ doc = new TestDocument(undefined, selection);
+ doc.init({
+ test : 'test'
+ , numbers : [4,5,6,7]
+ , nested : {
+ age : 5
+ , cool : DocumentObjectId.fromString('4c6c2d6240ced95d0e00003c')
+ , path : 'my path'
+ , deep : { x: 'a string' }
+ }
+ , notapath: 'i am not in the schema'
+ });
+
+ doc.isSelected('_id').should.be.false;
+ doc.isSelected('nested.deep.x.no').should.be.true;
+
+ doc = new TestDocument({ test: 'boom' });
+ doc.isSelected('_id').should.be.true;
+ doc.isSelected('test').should.be.true;
+ doc.isSelected('numbers').should.be.true;
+ doc.isSelected('oids').should.be.true;
+ doc.isSelected('nested').should.be.true;
+ doc.isSelected('nested.age').should.be.true;
+ doc.isSelected('nested.cool').should.be.true;
+ doc.isSelected('nested.path').should.be.true;
+ doc.isSelected('nested.deep').should.be.true;
+ doc.isSelected('nested.nope').should.be.true;
+ doc.isSelected('nested.deep.x').should.be.true;
+ doc.isSelected('nested.deep.x.no').should.be.true;
+ doc.isSelected('nested.deep.y').should.be.true;
+ doc.isSelected('noway').should.be.true;
+ doc.isSelected('notapath').should.be.true;
+ doc.isSelected('em').should.be.true;
+ doc.isSelected('em.title').should.be.true;
+ doc.isSelected('em.body').should.be.true;
+ doc.isSelected('em.nonpath').should.be.true;
+
+ doc = new TestDocument({ test: 'boom' }, true);
+ doc.isSelected('_id').should.be.true;
+ doc.isSelected('test').should.be.true;
+ doc.isSelected('numbers').should.be.true;
+ doc.isSelected('oids').should.be.true;
+ doc.isSelected('nested').should.be.true;
+ doc.isSelected('nested.age').should.be.true;
+ doc.isSelected('nested.cool').should.be.true;
+ doc.isSelected('nested.path').should.be.true;
+ doc.isSelected('nested.deep').should.be.true;
+ doc.isSelected('nested.nope').should.be.true;
+ doc.isSelected('nested.deep.x').should.be.true;
+ doc.isSelected('nested.deep.x.no').should.be.true;
+ doc.isSelected('nested.deep.y').should.be.true;
+ doc.isSelected('noway').should.be.true;
+ doc.isSelected('notapath').should.be.true;
+ doc.isSelected('em').should.be.true;
+ doc.isSelected('em.title').should.be.true;
+ doc.isSelected('em.body').should.be.true;
+ doc.isSelected('em.nonpath').should.be.true;
+ },
+
+ 'unselected required fields should pass validation': function () {
+ var db = start()
+ , Tschema = new Schema({ name: String, req: { type: String, required: true }})
+ , T = db.model('unselectedRequiredFieldValidation', Tschema);
+
+ var t = new T({ name: 'teeee', req: 'i am required' });
+ t.save(function (err) {
+ should.strictEqual(null, err);
+ T.findById(t).select('name').exec(function (err, t) {
+ should.strictEqual(null, err);
+ should.strictEqual(undefined, t.req);
+ t.name = 'wooo';
+ t.save(function (err) {
+ should.strictEqual(null, err);
+
+ T.findById(t).select('name').exec(function (err, t) {
+ should.strictEqual(null, err);
+ t.req = undefined;
+ t.save(function (err) {
+ err = String(err);
+ var invalid = /Validator "required" failed for path req/.test(err);
+ invalid.should.be.true;
+ t.req = 'it works again'
+ t.save(function (err) {
+ db.close();
+ should.strictEqual(null, err);
+ });
+ });
+ });
+ });
+ });
+ });
+ }
+};