* Module dependencies.
*/
'use strict';
const start = require('./common');
const Document = require('../lib/document');
const EventEmitter = require('events').EventEmitter;
const assert = require('assert');
const mongoose = start.mongoose;
const Schema = mongoose.Schema;
const ObjectId = Schema.ObjectId;
const DocumentObjectId = mongoose.Types.ObjectId;
* Test Document constructor.
*/
function TestDocument() {
Document.apply(this, arguments);
}
* Inherits from Document.
*/
Object.setPrototypeOf(TestDocument.prototype, Document.prototype);
for (const i in EventEmitter.prototype) {
TestDocument[i] = EventEmitter.prototype[i];
}
* Set a dummy schema to simulate compilation.
*/
const em = new Schema({ title: String, body: String });
em.virtual('works').get(function() {
return 'em virtual works';
});
const 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],
date: Date
});
TestDocument.prototype.$__setSchema(schema);
schema.virtual('nested.agePlus2').get(function() {
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';
});
schema.path('date').set(function(v) {
assert.equal(typeof v, 'string');
return v;
});
* Method subject to hooks. Simply fires the callback once the hooks are
* executed.
*/
TestDocument.prototype.hooksTest = function(fn) {
fn(null, arguments);
};
* Test.
*/
describe('document', function() {
it('isSelected()', function() {
let doc = new TestDocument();
doc.init({
test: 'test',
numbers: [4, 5, 6, 7],
nested: {
age: 5,
cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
path: 'my path',
deep: { x: 'a string' }
},
notapath: 'i am not in the schema',
em: [{ title: 'gocars' }]
});
assert.ok(doc.isSelected('_id'));
assert.ok(doc.isSelected('test'));
assert.ok(doc.isSelected('numbers'));
assert.ok(doc.isSelected('oids'));
assert.ok(doc.isSelected('nested'));
assert.ok(doc.isSelected('nested.age'));
assert.ok(doc.isSelected('nested.cool'));
assert.ok(doc.isSelected('nested.path'));
assert.ok(doc.isSelected('nested.deep'));
assert.ok(doc.isSelected('nested.nope'));
assert.ok(doc.isSelected('nested.deep.x'));
assert.ok(doc.isSelected('nested.deep.x.no'));
assert.ok(doc.isSelected('nested.deep.y'));
assert.ok(doc.isSelected('noway'));
assert.ok(doc.isSelected('notapath'));
assert.ok(doc.isSelected('em'));
assert.ok(doc.isSelected('em.title'));
assert.ok(doc.isSelected('em.body'));
assert.ok(doc.isSelected('em.nonpath'));
let 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' }
}
});
assert.ok(doc.isSelected('_id'));
assert.ok(doc.isSelected('test'));
assert.ok(doc.isSelected('numbers'));
assert.ok(doc.isSelected('oids'));
assert.ok(doc.isSelected('nested'));
assert.ok(!doc.isSelected('nested.age'));
assert.ok(!doc.isSelected('nested.cool'));
assert.ok(!doc.isSelected('nested.path'));
assert.ok(doc.isSelected('nested.deep'));
assert.ok(!doc.isSelected('nested.nope'));
assert.ok(doc.isSelected('nested.deep.x'));
assert.ok(doc.isSelected('nested.deep.x.no'));
assert.ok(doc.isSelected('nested.deep.y'));
assert.ok(!doc.isSelected('noway'));
assert.ok(!doc.isSelected('notapath'));
assert.ok(!doc.isSelected('em'));
assert.ok(!doc.isSelected('em.title'));
assert.ok(!doc.isSelected('em.body'));
assert.ok(!doc.isSelected('em.nonpath'));
assert.ok(doc.isSelected('_id test'));
assert.ok(doc.isSelected('test nested.nope'));
assert.ok(!doc.isSelected('nested.path nested.nope'));
assert.ok(doc.isSelected(['_id', 'test']));
assert.ok(doc.isSelected(['test', 'nested.nope']));
assert.ok(!doc.isSelected(['nested.path', 'nested.nope']));
selection = {
'em.title': 1
};
doc = new TestDocument(undefined, selection);
doc.init({
em: [{ title: 'one' }]
});
assert.ok(doc.isSelected('_id'));
assert.ok(!doc.isSelected('test'));
assert.ok(!doc.isSelected('numbers'));
assert.ok(!doc.isSelected('oids'));
assert.ok(!doc.isSelected('nested'));
assert.ok(!doc.isSelected('nested.age'));
assert.ok(!doc.isSelected('nested.cool'));
assert.ok(!doc.isSelected('nested.path'));
assert.ok(!doc.isSelected('nested.deep'));
assert.ok(!doc.isSelected('nested.nope'));
assert.ok(!doc.isSelected('nested.deep.x'));
assert.ok(!doc.isSelected('nested.deep.x.no'));
assert.ok(!doc.isSelected('nested.deep.y'));
assert.ok(!doc.isSelected('noway'));
assert.ok(!doc.isSelected('notapath'));
assert.ok(doc.isSelected('em'));
assert.ok(doc.isSelected('em.title'));
assert.ok(!doc.isSelected('em.body'));
assert.ok(!doc.isSelected('em.nonpath'));
selection = {
em: 0
};
doc = new TestDocument(undefined, selection);
doc.init({
test: 'test',
numbers: [4, 5, 6, 7],
nested: {
age: 5,
cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
path: 'my path',
deep: { x: 'a string' }
},
notapath: 'i am not in the schema'
});
assert.ok(doc.isSelected('_id'));
assert.ok(doc.isSelected('test'));
assert.ok(doc.isSelected('numbers'));
assert.ok(doc.isSelected('oids'));
assert.ok(doc.isSelected('nested'));
assert.ok(doc.isSelected('nested.age'));
assert.ok(doc.isSelected('nested.cool'));
assert.ok(doc.isSelected('nested.path'));
assert.ok(doc.isSelected('nested.deep'));
assert.ok(doc.isSelected('nested.nope'));
assert.ok(doc.isSelected('nested.deep.x'));
assert.ok(doc.isSelected('nested.deep.x.no'));
assert.ok(doc.isSelected('nested.deep.y'));
assert.ok(doc.isSelected('noway'));
assert.ok(doc.isSelected('notapath'));
assert.ok(!doc.isSelected('em'));
assert.ok(!doc.isSelected('em.title'));
assert.ok(!doc.isSelected('em.body'));
assert.ok(!doc.isSelected('em.nonpath'));
selection = {
_id: 0
};
doc = new TestDocument(undefined, selection);
doc.init({
test: 'test',
numbers: [4, 5, 6, 7],
nested: {
age: 5,
cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
path: 'my path',
deep: { x: 'a string' }
},
notapath: 'i am not in the schema'
});
assert.ok(!doc.isSelected('_id'));
assert.ok(doc.isSelected('nested.deep.x.no'));
doc = new TestDocument({ test: 'boom' });
assert.ok(doc.isSelected('_id'));
assert.ok(doc.isSelected('test'));
assert.ok(doc.isSelected('numbers'));
assert.ok(doc.isSelected('oids'));
assert.ok(doc.isSelected('nested'));
assert.ok(doc.isSelected('nested.age'));
assert.ok(doc.isSelected('nested.cool'));
assert.ok(doc.isSelected('nested.path'));
assert.ok(doc.isSelected('nested.deep'));
assert.ok(doc.isSelected('nested.nope'));
assert.ok(doc.isSelected('nested.deep.x'));
assert.ok(doc.isSelected('nested.deep.x.no'));
assert.ok(doc.isSelected('nested.deep.y'));
assert.ok(doc.isSelected('noway'));
assert.ok(doc.isSelected('notapath'));
assert.ok(doc.isSelected('em'));
assert.ok(doc.isSelected('em.title'));
assert.ok(doc.isSelected('em.body'));
assert.ok(doc.isSelected('em.nonpath'));
selection = {
_id: 1
};
doc = new TestDocument(undefined, selection);
doc.init({ _id: 'test' });
assert.ok(doc.isSelected('_id'));
assert.ok(!doc.isSelected('test'));
doc = new TestDocument({ test: 'boom' }, true);
assert.ok(doc.isSelected('_id'));
assert.ok(doc.isSelected('test'));
assert.ok(doc.isSelected('numbers'));
assert.ok(doc.isSelected('oids'));
assert.ok(doc.isSelected('nested'));
assert.ok(doc.isSelected('nested.age'));
assert.ok(doc.isSelected('nested.cool'));
assert.ok(doc.isSelected('nested.path'));
assert.ok(doc.isSelected('nested.deep'));
assert.ok(doc.isSelected('nested.nope'));
assert.ok(doc.isSelected('nested.deep.x'));
assert.ok(doc.isSelected('nested.deep.x.no'));
assert.ok(doc.isSelected('nested.deep.y'));
assert.ok(doc.isSelected('noway'));
assert.ok(doc.isSelected('notapath'));
assert.ok(doc.isSelected('em'));
assert.ok(doc.isSelected('em.title'));
assert.ok(doc.isSelected('em.body'));
assert.ok(doc.isSelected('em.nonpath'));
selection = {
_id: 1,
n: 1
};
doc = new TestDocument(undefined, selection);
doc.init({
test: 'test',
numbers: [4, 5, 6, 7],
nested: {
age: 5,
cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
path: 'my path',
deep: { x: 'a string' }
},
notapath: 'i am not in the schema'
});
assert.ok(doc.isSelected('_id'));
assert.ok(doc.isSelected('n'));
assert.ok(!doc.isSelected('nested'));
assert.ok(!doc.isSelected('nested.age'));
assert.ok(!doc.isSelected('numbers'));
});
it('isDirectSelected (gh-5063)', function() {
const selection = {
test: 1,
numbers: 1,
'nested.deep': 1,
oids: 1
};
const doc = new TestDocument(undefined, selection);
doc.init({
test: 'test',
numbers: [4, 5, 6, 7],
nested: {
deep: { x: 'a string' }
}
});
assert.ok(doc.isDirectSelected('nested.deep'));
assert.ok(!doc.isDirectSelected('nested.cool'));
assert.ok(!doc.isDirectSelected('nested'));
assert.ok(doc.isDirectSelected('nested.deep nested'));
assert.ok(!doc.isDirectSelected('nested.cool nested'));
assert.ok(doc.isDirectSelected(['nested.deep', 'nested']));
assert.ok(!doc.isDirectSelected(['nested.cool', 'nested']));
});
describe('flat projections (gh-16373)', function() {
it('inclusive projection with no nested keys', function() {
const doc = new TestDocument(undefined, { test: 1, numbers: 1 });
assert.ok(doc.isSelected('test'));
assert.ok(doc.isSelected('numbers'));
assert.ok(doc.isSelected('_id'));
assert.ok(!doc.isSelected('nested'));
assert.ok(!doc.isSelected('nested.age'));
assert.ok(!doc.isSelected('nested.deep.x'));
assert.ok(!doc.isSelected('date'));
});
it('exclusive projection with no nested keys', function() {
const doc = new TestDocument(undefined, { nested: 0 });
assert.ok(doc.isSelected('test'));
assert.ok(doc.isSelected('date'));
assert.ok(!doc.isSelected('nested'));
assert.ok(!doc.isSelected('nested.age'));
assert.ok(!doc.isSelected('nested.deep.x'));
});
it('projecting a parent selects its children', function() {
const doc = new TestDocument(undefined, { nested: 1 });
assert.ok(doc.isSelected('nested'));
assert.ok(doc.isSelected('nested.age'));
assert.ok(doc.isSelected('nested.deep.x'));
assert.ok(!doc.isSelected('test'));
});
it('agrees with nested projections that select the same paths', function() {
const flat = new TestDocument(undefined, { nested: 1 });
const nested = new TestDocument(undefined, { nested: 1, 'nested2.yup': 1 });
for (const path of ['nested', 'nested.age', 'nested.deep.x', 'test', 'date']) {
assert.equal(
flat.isSelected(path),
nested.isSelected(path),
`disagreement on ${path}`
);
}
});
});
});