summaryrefslogtreecommitdiff
path: root/node_modules/mongoose/test/schema.test.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/mongoose/test/schema.test.js')
-rw-r--r--node_modules/mongoose/test/schema.test.js978
1 files changed, 978 insertions, 0 deletions
diff --git a/node_modules/mongoose/test/schema.test.js b/node_modules/mongoose/test/schema.test.js
new file mode 100644
index 0000000..93a3545
--- /dev/null
+++ b/node_modules/mongoose/test/schema.test.js
@@ -0,0 +1,978 @@
+
+/**
+ * Module dependencies.
+ */
+
+var mongoose = require('./common').mongoose
+ , should = require('should')
+ , Schema = mongoose.Schema
+ , Document = mongoose.Document
+ , SchemaType = mongoose.SchemaType
+ , VirtualType = mongoose.VirtualType
+ , ObjectId = Schema.ObjectId
+ , ValidatorError = SchemaType.ValidatorError
+ , CastError = SchemaType.CastError
+ , SchemaTypes = Schema.Types
+ , DocumentObjectId = mongoose.Types.ObjectId
+ , Mixed = SchemaTypes.Mixed
+ , MongooseNumber = mongoose.Types.Number
+ , MongooseArray = mongoose.Types.Array
+ , vm = require('vm')
+
+/**
+ * Test Document constructor.
+ */
+
+function TestDocument () {
+ Document.apply(this, arguments);
+};
+
+/**
+ * Inherits from Document.
+ */
+
+TestDocument.prototype.__proto__ = Document.prototype;
+
+/**
+ * Set a dummy schema to simulate compilation.
+ */
+
+TestDocument.prototype.schema = new Schema({
+ test : String
+});
+
+/**
+ * Test.
+ */
+
+module.exports = {
+
+ 'test different schema types support': function(){
+ var Checkin = new Schema({
+ date : Date
+ , location : {
+ lat: Number
+ , lng: Number
+ }
+ });
+
+ var Ferret = new Schema({
+ name : String
+ , owner : ObjectId
+ , fur : String
+ , color : { type: String }
+ , age : Number
+ , checkins : [Checkin]
+ , friends : [ObjectId]
+ , likes : Array
+ , alive : Boolean
+ , extra : Mixed
+ });
+
+ Ferret.path('name').should.be.an.instanceof(SchemaTypes.String);
+ Ferret.path('owner').should.be.an.instanceof(SchemaTypes.ObjectId);
+ Ferret.path('fur').should.be.an.instanceof(SchemaTypes.String);
+ Ferret.path('color').should.be.an.instanceof(SchemaTypes.String);
+ Ferret.path('age').should.be.an.instanceof(SchemaTypes.Number);
+ Ferret.path('checkins').should.be.an.instanceof(SchemaTypes.DocumentArray);
+ Ferret.path('friends').should.be.an.instanceof(SchemaTypes.Array);
+ Ferret.path('likes').should.be.an.instanceof(SchemaTypes.Array);
+ Ferret.path('alive').should.be.an.instanceof(SchemaTypes.Boolean);
+ Ferret.path('extra').should.be.an.instanceof(SchemaTypes.Mixed);
+
+ should.strictEqual(Ferret.path('unexistent'), undefined);
+
+ Checkin.path('date').should.be.an.instanceof(SchemaTypes.Date);
+ },
+
+ 'dot notation support for accessing paths': function(){
+ var Racoon = new Schema({
+ name : { type: String, enum: ['Edwald', 'Tobi'] }
+ , age : Number
+ });
+
+ var Person = new Schema({
+ name : String
+ , raccoons : [Racoon]
+ , location : {
+ city : String
+ , state : String
+ }
+ });
+
+ Person.path('name').should.be.an.instanceof(SchemaTypes.String);
+ Person.path('raccoons').should.be.an.instanceof(SchemaTypes.DocumentArray);
+ Person.path('location.city').should.be.an.instanceof(SchemaTypes.String);
+ Person.path('location.state').should.be.an.instanceof(SchemaTypes.String);
+
+ should.strictEqual(Person.path('location.unexistent'), undefined);
+ },
+
+ 'nested paths more than 2 levels deep': function () {
+ var Nested = new Schema({
+ first: {
+ second: {
+ third: String
+ }
+ }
+ });
+ Nested.path('first.second.third').should.be.an.instanceof(SchemaTypes.String);
+ },
+
+ 'test default definition': function(){
+ var Test = new Schema({
+ simple : { type: String, default: 'a' }
+ , array : { type: Array, default: [1,2,3,4,5] }
+ , arrayX : { type: Array, default: 9 }
+ , arrayFn : { type: Array, default: function () { return [8] } }
+ , callback : { type: Number, default: function(){
+ this.a.should.eql('b');
+ return '3';
+ }}
+ });
+
+ Test.path('simple').defaultValue.should.eql('a');
+ Test.path('callback').defaultValue.should.be.a('function');
+
+ Test.path('simple').getDefault().should.eql('a');
+ (+Test.path('callback').getDefault({ a: 'b' })).should.eql(3);
+ Test.path('array').defaultValue.should.be.a('function');
+ Test.path('array').getDefault(new TestDocument)[3].should.eql(4);
+ Test.path('arrayX').getDefault(new TestDocument)[0].should.eql(9);
+ Test.path('arrayFn').defaultValue.should.be.a('function');
+ Test.path('arrayFn').getDefault(new TestDocument).should.be.an.instanceof(MongooseArray);
+ },
+
+ 'test Mixed defaults can be empty arrays': function () {
+ var Test = new Schema({
+ mixed1 : { type: Mixed, default: [] }
+ , mixed2 : { type: Mixed, default: Array }
+ });
+
+ Test.path('mixed1').getDefault().should.be.an.instanceof(Array);
+ Test.path('mixed1').getDefault().length.should.be.eql(0);
+ Test.path('mixed2').getDefault().should.be.an.instanceof(Array);
+ Test.path('mixed2').getDefault().length.should.be.eql(0);
+ },
+
+ 'test string required validation': function(){
+ var Test = new Schema({
+ simple: String
+ });
+
+ Test.path('simple').required(true);
+ Test.path('simple').validators.should.have.length(1);
+
+ Test.path('simple').doValidate(null, function(err){
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Test.path('simple').doValidate(undefined, function(err){
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Test.path('simple').doValidate('', function(err){
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Test.path('simple').doValidate('woot', function(err){
+ should.strictEqual(err, null);
+ });
+ },
+
+ 'test string enum validation': function(){
+ var Test = new Schema({
+ complex: { type: String, enum: ['a', 'b', undefined, 'c', null] }
+ });
+
+ Test.path('complex').should.be.an.instanceof(SchemaTypes.String);
+ Test.path('complex').enumValues.should.eql(['a', 'b', 'c', null]);
+ Test.path('complex').validators.should.have.length(1);
+
+ Test.path('complex').enum('d', 'e');
+
+ Test.path('complex').enumValues.should.eql(['a', 'b', 'c', null, 'd', 'e']);
+
+ Test.path('complex').doValidate('x', function(err){
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Test.path('complex').doValidate(undefined, function(err){
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Test.path('complex').doValidate(null, function(err){
+ should.strictEqual(null, err);
+ });
+
+ Test.path('complex').doValidate('da', function(err){
+ err.should.be.an.instanceof(ValidatorError);
+ });
+ },
+
+ 'test string regular expression validation': function(){
+ var Test = new Schema({
+ simple: { type: String, match: /[a-z]/ }
+ });
+
+ Test.path('simple').validators.should.have.length(1);
+
+ Test.path('simple').doValidate('az', function(err){
+ should.strictEqual(err, null);
+ });
+
+ Test.path('simple').match(/[0-9]/);
+ Test.path('simple').validators.should.have.length(2);
+
+ Test.path('simple').doValidate('12', function(err){
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Test.path('simple').doValidate('a12', function(err){
+ should.strictEqual(err, null);
+ });
+ },
+
+ 'test string casting': function(){
+ var Tobi = new Schema({
+ nickname: String
+ });
+
+ function Test(){};
+ Test.prototype.toString = function(){
+ return 'woot';
+ };
+
+ // test Number -> String cast
+ Tobi.path('nickname').cast(0).should.be.a('string');
+ Tobi.path('nickname').cast(0).should.eql('0');
+
+ // test any object that implements toString
+ Tobi.path('nickname').cast(new Test()).should.be.a('string');
+ Tobi.path('nickname').cast(new Test()).should.eql('woot');
+ },
+
+ 'test number minimums and maximums validation': function(){
+ var Tobi = new Schema({
+ friends: { type: Number, max: 15, min: 5 }
+ });
+
+ Tobi.path('friends').validators.should.have.length(2);
+
+ Tobi.path('friends').doValidate(10, function(err){
+ should.strictEqual(err, null);
+ });
+
+ Tobi.path('friends').doValidate(100, function(err){
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Tobi.path('friends').doValidate(1, function(err){
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ // null is allowed
+ Tobi.path('friends').doValidate(null, function(err){
+ should.strictEqual(err, null);
+ });
+ },
+
+ 'test number required validation': function(){
+ var Edwald = new Schema({
+ friends: { type: Number, required: true }
+ });
+
+ Edwald.path('friends').doValidate(null, function(err){
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Edwald.path('friends').doValidate(undefined, function(err){
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Edwald.path('friends').doValidate(0, function(err){
+ should.strictEqual(err, null);
+ });
+ },
+
+ 'test number casting': function(){
+ var Tobi = new Schema({
+ age: Number
+ });
+
+ // test String -> Number cast
+ Tobi.path('age').cast('0').should.be.an.instanceof(MongooseNumber);
+ (+Tobi.path('age').cast('0')).should.eql(0);
+
+ Tobi.path('age').cast(0).should.be.an.instanceof(MongooseNumber);
+ (+Tobi.path('age').cast(0)).should.eql(0);
+ },
+
+ 'test date required validation': function(){
+ var Loki = new Schema({
+ birth_date: { type: Date, required: true }
+ });
+
+ Loki.path('birth_date').doValidate(null, function (err) {
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Loki.path('birth_date').doValidate(undefined, function (err) {
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Loki.path('birth_date').doValidate(new Date(), function (err) {
+ should.strictEqual(err, null);
+ });
+ },
+
+ 'test date casting': function(){
+ var Loki = new Schema({
+ birth_date: { type: Date }
+ });
+
+ Loki.path('birth_date').cast(1294525628301).should.be.an.instanceof(Date);
+ Loki.path('birth_date').cast('8/24/2000').should.be.an.instanceof(Date);
+ Loki.path('birth_date').cast(new Date).should.be.an.instanceof(Date);
+ },
+
+ 'test object id required validator': function(){
+ var Loki = new Schema({
+ owner: { type: ObjectId, required: true }
+ });
+
+ Loki.path('owner').doValidate(new DocumentObjectId(), function(err){
+ should.strictEqual(err, null);
+ });
+
+ Loki.path('owner').doValidate(null, function(err){
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Loki.path('owner').doValidate(undefined, function(err){
+ err.should.be.an.instanceof(ValidatorError);
+ });
+ },
+
+ 'test object id casting': function(){
+ var Loki = new Schema({
+ owner: { type: ObjectId }
+ });
+
+ var doc = new TestDocument()
+ , id = doc._id.toString();
+
+ Loki.path('owner').cast('4c54f3453e688c000000001a')
+ .should.be.an.instanceof(DocumentObjectId);
+
+ Loki.path('owner').cast(new DocumentObjectId())
+ .should.be.an.instanceof(DocumentObjectId);
+
+ Loki.path('owner').cast(doc)
+ .should.be.an.instanceof(DocumentObjectId);
+
+ Loki.path('owner').cast(doc).toString().should.eql(id);
+ },
+
+ 'test array required validation': function(){
+ var Loki = new Schema({
+ likes: { type: Array, required: true }
+ });
+
+ Loki.path('likes').doValidate(null, function (err) {
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Loki.path('likes').doValidate(undefined, function (err) {
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Loki.path('likes').doValidate([], function (err) {
+ err.should.be.an.instanceof(ValidatorError);
+ });
+ },
+
+ 'test array casting': function(){
+ var Loki = new Schema({
+ oids : [ObjectId]
+ , dates : [Date]
+ , numbers : [Number]
+ , strings : [String]
+ , buffers : [Buffer]
+ , nocast : []
+ , mixed : [Mixed]
+ });
+
+ var oids = Loki.path('oids').cast(['4c54f3453e688c000000001a', new DocumentObjectId]);
+
+ oids[0].should.be.an.instanceof(DocumentObjectId);
+ oids[1].should.be.an.instanceof(DocumentObjectId);
+
+ var dates = Loki.path('dates').cast(['8/24/2010', 1294541504958]);
+
+ dates[0].should.be.an.instanceof(Date);
+ dates[1].should.be.an.instanceof(Date);
+
+ var numbers = Loki.path('numbers').cast([152, '31']);
+
+ numbers[0].should.be.a('number');
+ numbers[1].should.be.a('number');
+
+ var strings = Loki.path('strings').cast(['test', 123]);
+
+ strings[0].should.be.a('string');
+ strings[0].should.eql('test');
+
+ strings[1].should.be.a('string');
+ strings[1].should.eql('123');
+
+ var buffers = Loki.path('buffers').cast(['\0\0\0', new Buffer("abc")]);
+
+ buffers[0].should.be.an.instanceof(Buffer);
+ buffers[1].should.be.an.instanceof(Buffer);
+
+ var nocasts = Loki.path('nocast').cast(['test', 123]);
+
+ nocasts[0].should.be.a('string');
+ nocasts[0].should.eql('test');
+
+ nocasts[1].should.be.a('number');
+ nocasts[1].should.eql(123);
+
+ var mixed = Loki.path('mixed').cast(['test', 123, '123', {}, new Date, new DocumentObjectId]);
+
+ mixed[0].should.be.a('string');
+ mixed[1].should.be.a('number');
+ mixed[2].should.be.a('string');
+ mixed[3].should.be.a('object');
+ mixed[4].should.be.an.instanceof(Date);
+ mixed[5].should.be.an.instanceof(DocumentObjectId);
+ },
+
+ 'test boolean required validator': function(){
+ var Animal = new Schema({
+ isFerret: { type: Boolean, required: true }
+ });
+
+ Animal.path('isFerret').doValidate(null, function(err){
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Animal.path('isFerret').doValidate(undefined, function(err){
+ err.should.be.an.instanceof(ValidatorError);
+ });
+
+ Animal.path('isFerret').doValidate(true, function(err){
+ should.strictEqual(err, null);
+ });
+
+ Animal.path('isFerret').doValidate(false, function(err){
+ should.strictEqual(err, null);
+ });
+ },
+
+ 'test boolean casting': function(){
+ var Animal = new Schema({
+ isFerret: { type: Boolean, required: true }
+ });
+
+ should.strictEqual(Animal.path('isFerret').cast(null), null);
+ Animal.path('isFerret').cast(undefined).should.be.false;
+ Animal.path('isFerret').cast(false).should.be.false;
+ Animal.path('isFerret').cast(0).should.be.false;
+ Animal.path('isFerret').cast('0').should.be.false;
+ Animal.path('isFerret').cast({}).should.be.true;
+ Animal.path('isFerret').cast(true).should.be.true;
+ Animal.path('isFerret').cast(1).should.be.true;
+ Animal.path('isFerret').cast('1').should.be.true;
+ },
+
+ 'test async multiple validators': function(beforeExit){
+ var executed = 0;
+
+ function validator (value, fn) {
+ setTimeout(function(){
+ executed++;
+ fn(value === true);
+ }, 50);
+ };
+
+ var Animal = new Schema({
+ ferret: {
+ type: Boolean,
+ validate: [
+ {
+ 'validator': validator,
+ 'msg': 'validator1'
+ },
+ {
+ 'validator': validator,
+ 'msg': 'validator2'
+ },
+ ],
+ }
+ });
+
+ Animal.path('ferret').doValidate(true, function(err){
+ should.strictEqual(err, null);
+ });
+
+ beforeExit(function(){
+ executed.should.eql(2);
+ });
+ },
+
+ 'test async validators': function(beforeExit){
+ var executed = 0;
+
+ function validator (value, fn) {
+ setTimeout(function(){
+ executed++;
+ fn(value === true);
+ }, 50);
+ };
+
+ var Animal = new Schema({
+ ferret: { type: Boolean, validate: validator }
+ });
+
+ Animal.path('ferret').doValidate(true, function(err){
+ should.strictEqual(err, null);
+ });
+
+ Animal.path('ferret').doValidate(false, function(err){
+ err.should.be.an.instanceof(Error);
+ });
+
+ beforeExit(function(){
+ executed.should.eql(2);
+ });
+ },
+
+ 'test async validators scope': function(beforeExit){
+ var executed = false;
+
+ function validator (value, fn) {
+ this.a.should.eql('b');
+
+ setTimeout(function(){
+ executed = true;
+ fn(true);
+ }, 50);
+ };
+
+ var Animal = new Schema({
+ ferret: { type: Boolean, validate: validator }
+ });
+
+ Animal.path('ferret').doValidate(true, function(err){
+ should.strictEqual(err, null);
+ }, { a: 'b' });
+
+ beforeExit(function(){
+ executed.should.be.true;
+ });
+ },
+
+ 'test declaring new methods': function(){
+ var a = new Schema();
+ a.method('test', function(){});
+ a.method({
+ a: function(){}
+ , b: function(){}
+ });
+
+ Object.keys(a.methods).should.have.length(3);
+ },
+
+ 'test declaring new statics': function(){
+ var a = new Schema();
+ a.static('test', function(){});
+ a.static({
+ a: function(){}
+ , b: function(){}
+ , c: function(){}
+ });
+
+ Object.keys(a.statics).should.have.length(4);
+ },
+
+ 'test setter(s)': function(){
+ function lowercase (v) {
+ return v.toLowerCase();
+ };
+
+ var Tobi = new Schema({
+ name: { type: String, set: lowercase }
+ });
+
+ Tobi.path('name').applySetters('WOOT').should.eql('woot');
+ Tobi.path('name').setters.should.have.length(1);
+
+ Tobi.path('name').set(function(v){
+ return v + 'WOOT';
+ });
+
+ Tobi.path('name').applySetters('WOOT').should.eql('wootwoot');
+ Tobi.path('name').setters.should.have.length(2);
+ },
+
+ 'test setters scope': function(){
+ function lowercase (v, self) {
+ this.a.should.eql('b');
+ self.path.should.eql('name');
+ return v.toLowerCase();
+ };
+
+ var Tobi = new Schema({
+ name: { type: String, set: lowercase }
+ });
+
+ Tobi.path('name').applySetters('WHAT', { a: 'b' }).should.eql('what');
+ },
+
+ 'test string built-in setter `lowercase`': function () {
+ var Tobi = new Schema({
+ name: { type: String, lowercase: true }
+ });
+
+ Tobi.path('name').applySetters('WHAT').should.eql('what');
+ },
+
+ 'test string built-in setter `uppercase`': function () {
+ var Tobi = new Schema({
+ name: { type: String, uppercase: true }
+ });
+
+ Tobi.path('name').applySetters('what').should.eql('WHAT');
+ },
+
+ 'test string built-in setter `trim`': function () {
+ var Tobi = new Schema({
+ name: { type: String, uppercase: true, trim: true }
+ });
+
+ Tobi.path('name').applySetters(' what ').should.eql('WHAT');
+ },
+
+ 'test getter(s)': function(){
+ function woot (v) {
+ return v + ' woot';
+ };
+
+ var Tobi = new Schema({
+ name: { type: String, get: woot }
+ });
+
+ Tobi.path('name').getters.should.have.length(1);
+ Tobi.path('name').applyGetters('test').should.eql('test woot');
+ },
+
+ 'test getters scope': function(){
+ function woot (v, self) {
+ this.a.should.eql('b');
+ self.path.should.eql('name');
+ return v.toLowerCase();
+ };
+
+ var Tobi = new Schema({
+ name: { type: String, get: woot }
+ });
+
+ Tobi.path('name').applyGetters('YEP', { a: 'b' }).should.eql('yep');
+ },
+
+ 'test setters casting': function(){
+ function last (v) {
+ v.should.be.a('string');
+ v.should.eql('0');
+ return 'last';
+ };
+
+ function first (v) {
+ return 0;
+ };
+
+ var Tobi = new Schema({
+ name: { type: String, set: last }
+ });
+
+ Tobi.path('name').set(first);
+ Tobi.path('name').applySetters('woot').should.eql('last');
+ },
+
+ 'test getters casting': function(){
+ function last (v) {
+ v.should.be.a('string');
+ v.should.eql('0');
+ return 'last';
+ };
+
+ function first (v) {
+ return 0;
+ };
+
+ var Tobi = new Schema({
+ name: { type: String, get: last }
+ });
+
+ Tobi.path('name').get(first);
+ Tobi.path('name').applyGetters('woot').should.eql('last');
+ },
+
+ 'test hooks registration': function(){
+ var Tobi = new Schema();
+
+ Tobi.pre('save', function(){});
+ Tobi.callQueue.should.have.length(1);
+
+ Tobi.post('save', function(){});
+ Tobi.callQueue.should.have.length(2);
+
+ Tobi.pre('save', function(){});
+ Tobi.callQueue.should.have.length(3);
+ },
+
+ 'test applying setters when none have been defined': function(){
+ var Tobi = new Schema({
+ name: String
+ });
+
+ Tobi.path('name').applySetters('woot').should.eql('woot');
+ },
+
+ 'test applying getters when none have been defined': function(){
+ var Tobi = new Schema({
+ name: String
+ });
+
+ Tobi.path('name').applyGetters('woot').should.eql('woot');
+ },
+
+ 'test defining an index': function(){
+ var Tobi = new Schema({
+ name: { type: String, index: true }
+ });
+
+ Tobi.path('name')._index.should.be.true;
+ Tobi.path('name').index({ unique: true });
+ Tobi.path('name')._index.should.eql({ unique: true });
+ Tobi.path('name').unique(false);
+ Tobi.path('name')._index.should.eql({ unique: false});
+
+ var T1 = new Schema({
+ name: { type: String, sparse: true }
+ });
+ T1.path('name')._index.should.eql({ sparse: true });
+
+ var T2 = new Schema({
+ name: { type: String, unique: true }
+ });
+ T2.path('name')._index.should.eql({ unique: true });
+
+ var T3 = new Schema({
+ name: { type: String, sparse: true, unique: true }
+ });
+ T3.path('name')._index.should.eql({ sparse: true, unique: true });
+
+ var T4 = new Schema({
+ name: { type: String, unique: true, sparse: true }
+ });
+ var i = T4.path('name')._index;
+ i.unique.should.be.true;
+ i.sparse.should.be.true;
+
+ var T5 = new Schema({
+ name: { type: String, index: { sparse: true, unique: true } }
+ });
+ var i = T5.path('name')._index;
+ i.unique.should.be.true;
+ i.sparse.should.be.true;
+ },
+
+ 'test defining compound indexes': function(){
+ var Tobi = new Schema({
+ name: { type: String, index: true }
+ , last: { type: Number, sparse: true }
+ });
+
+ Tobi.index({ firstname: 1, last: 1 }, { unique: true });
+
+ Tobi.indexes.should.eql([
+ [{ name: 1 }, {}]
+ , [{ last: 1 }, { sparse: true }]
+ , [{ firstname: 1, last: 1}, {unique: true}]
+ ]);
+ },
+
+ 'test plugins': function (beforeExit) {
+ var Tobi = new Schema()
+ , called = false;
+
+ Tobi.plugin(function(schema){
+ schema.should.equal(Tobi);
+ called = true;
+ });
+
+ beforeExit(function () {
+ called.should.be.true;
+ });
+ },
+
+ 'test that default options are set': function () {
+ var Tobi = new Schema();
+
+ Tobi.options.should.be.a('object');
+ Tobi.options.safe.should.be.true;
+ },
+
+ 'test setting options': function () {
+ var Tobi = new Schema({}, { collection: 'users' });
+
+ Tobi.set('a', 'b');
+ Tobi.set('safe', false);
+ Tobi.options.collection.should.eql('users');
+
+ Tobi.options.a.should.eql('b');
+ Tobi.options.safe.should.be.false;
+ },
+
+ 'test declaring virtual attributes': function () {
+ var Contact = new Schema({
+ firstName: String
+ , lastName: String
+ });
+ Contact.virtual('fullName')
+ .get( function () {
+ return this.get('firstName') + ' ' + this.get('lastName');
+ }).set(function (fullName) {
+ var split = fullName.split(' ');
+ this.set('firstName', split[0]);
+ this.set('lastName', split[1]);
+ });
+
+ Contact.virtualpath('fullName').should.be.an.instanceof(VirtualType);
+ },
+
+ 'test GH-298 - The default creation of a virtual `id` should be muted when someone defines their own `id` attribute': function () {
+ new Schema({ id: String });
+ },
+
+ 'allow disabling the auto .id virtual': function () {
+ var schema = new Schema({ name: String }, { noVirtualId: true });
+ should.strictEqual(undefined, schema.virtuals.id);
+ },
+
+ 'selected option': function () {
+ var s = new Schema({ thought: { type: String, select: false }});
+ s.path('thought').selected.should.be.false;
+
+ var a = new Schema({ thought: { type: String, select: true }});
+ a.path('thought').selected.should.be.true;
+ },
+
+ 'schema creation works with objects from other contexts': function () {
+ var str = 'code = {' +
+ ' name: String' +
+ ', arr1: Array ' +
+ ', arr2: { type: [] }' +
+ ', date: Date ' +
+ ', num: { type: Number }' +
+ ', bool: Boolean' +
+ ', nest: { sub: { type: {}, required: true }}' +
+ '}';
+
+ var script = vm.createScript(str, 'testSchema.vm');
+ var sandbox = { code: null };
+ script.runInNewContext(sandbox);
+
+ var Ferret = new Schema(sandbox.code);
+ Ferret.path('nest.sub').should.be.an.instanceof(SchemaTypes.Mixed);
+ Ferret.path('name').should.be.an.instanceof(SchemaTypes.String);
+ Ferret.path('arr1').should.be.an.instanceof(SchemaTypes.Array);
+ Ferret.path('arr2').should.be.an.instanceof(SchemaTypes.Array);
+ Ferret.path('date').should.be.an.instanceof(SchemaTypes.Date);
+ Ferret.path('num').should.be.an.instanceof(SchemaTypes.Number);
+ Ferret.path('bool').should.be.an.instanceof(SchemaTypes.Boolean);
+ },
+
+ 'schema string casts undefined to "undefined"': function () {
+ var db= require('./common')();
+ var schema = new Schema({ arr: [String] });
+ var M = db.model('castingStringArrayWithUndefined', schema);
+ M.find({ arr: { $in: [undefined] }}, function (err) {
+ db.close();
+ should.equal(err && err.message, 'Cast to string failed for value "undefined"');
+ })
+ },
+
+ 'array of object literal missing a `type` is interpreted as Mixed': function () {
+ var s = new Schema({
+ arr: [
+ { something: { type: String } }
+ ]
+ });
+ },
+
+ 'helpful schema debugging msg': function () {
+ var err;
+ try {
+ new Schema({ name: { first: null } })
+ } catch (e) {
+ err = e;
+ }
+ err.message.should.equal('Invalid value for schema path `name.first`')
+ try {
+ new Schema({ age: undefined })
+ } catch (e) {
+ err = e;
+ }
+ err.message.should.equal('Invalid value for schema path `age`')
+ },
+
+ 'add() does not polute existing paths': function () {
+ var o = { name: String }
+ var s = new Schema(o);
+ s.add({ age: Number }, 'name.');
+ ;('age' in o.name).should.be.false;
+ },
+
+ // gh-700
+ 'nested schemas should throw': function () {
+ var a = new Schema({ title: String })
+ , err
+
+ try {
+ new Schema({ blah: Boolean, a: a });
+ } catch (err_) {
+ err = err_;
+ }
+
+ should.exist(err);
+ ;/Did you try nesting Schemas/.test(err.message).should.be.true;
+ },
+
+ 'non-function etters throw': function () {
+ var schema = new Schema({ fun: String });
+ var g, s;
+
+ try {
+ schema.path('fun').get(true);
+ } catch (err_) {
+ g = err_;
+ }
+
+ should.exist(g);
+ g.message.should.equal('A getter must be a function.');
+
+ try {
+ schema.path('fun').set(4);
+ } catch (err_) {
+ s = err_;
+ }
+
+ should.exist(s);
+ s.message.should.equal('A setter must be a function.');
+ }
+
+};