UNPKG

camo

Version:

A class-based ES6 ODM for Mongo-like databases.

633 lines (539 loc) 20.8 kB
'use strict'; const _ = require('lodash'); const expect = require('chai').expect; const connect = require('../index').connect; const Document = require('../index').Document; const Data = require('./data'); const getData1 = require('./util').data1; const getData2 = require('./util').data2; const validateData1 = require('./util').validateData1; const validateData2 = require('./util').validateData2; const validateId = require('./util').validateId; const isNativeId = require('../lib/validate').isNativeId; describe('Client', function() { const url = 'nedb://memory'; //const url = 'mongodb://localhost/camo_test'; let database = null; before(function(done) { connect(url).then(function(db) { database = db; return database.dropDatabase(); }).then(function() { return done(); }); }); beforeEach(function(done) { done(); }); afterEach(function(done) { database.dropDatabase().then(function() {}).then(done, done); }); after(function(done) { database.dropDatabase().then(function() {}).then(done, done); }); describe('#save()', function() { it('should persist the object and its members to the database', function(done) { let data = getData1(); data.save().then(function() { validateId(data); validateData1(data); }).then(done, done); }); }); class Address extends Document { constructor() { super(); this.street = String; this.city = String; this.zipCode = Number; } static collectionName() { return 'addresses'; } } class Pet extends Document { constructor() { super(); this.schema({ type: String, name: String, }); } } class User extends Document { constructor() { super(); this.schema({ firstName: String, lastName: String, pet: Pet, address: Address }); } } describe('#findOne()', function() { it('should load a single object from the collection', function(done) { let data = getData1(); data.save().then(function() { validateId(data); return Data.findOne({item:99}); }).then(function(d) { validateId(d); validateData1(d); }).then(done, done); }); it('should populate all fields', function(done) { let address = Address.create({ street: '123 Fake St.', city: 'Cityville', zipCode: 12345 }); let dog = Pet.create({ type: 'dog', name: 'Fido', }); let user = User.create({ firstName: 'Billy', lastName: 'Bob', pet: dog, address: address }); Promise.all([address.save(), dog.save()]).then(function() { validateId(address); validateId(dog); return user.save(); }).then(function() { validateId(user); return User.findOne({_id: user._id}, {populate: true}); }).then(function(u) { expect(u.pet).to.be.an.instanceof(Pet); expect(u.address).to.be.an.instanceof(Address); }).then(done, done); }); it('should not populate any fields', function(done) { let address = Address.create({ street: '123 Fake St.', city: 'Cityville', zipCode: 12345 }); let dog = Pet.create({ type: 'dog', name: 'Fido', }); let user = User.create({ firstName: 'Billy', lastName: 'Bob', pet: dog, address: address }); Promise.all([address.save(), dog.save()]).then(function() { validateId(address); validateId(dog); return user.save(); }).then(function() { validateId(user); return User.findOne({_id: user._id}, {populate: false}); }).then(function(u) { expect(isNativeId(u.pet)).to.be.true; expect(isNativeId(u.address)).to.be.true; }).then(done, done); }); it('should populate specified fields', function(done) { let address = Address.create({ street: '123 Fake St.', city: 'Cityville', zipCode: 12345 }); let dog = Pet.create({ type: 'dog', name: 'Fido', }); let user = User.create({ firstName: 'Billy', lastName: 'Bob', pet: dog, address: address }); Promise.all([address.save(), dog.save()]).then(function() { validateId(address); validateId(dog); return user.save(); }).then(function() { validateId(user); return User.findOne({_id: user._id}, {populate: ['pet']}); }).then(function(u) { expect(u.pet).to.be.an.instanceof(Pet); expect(isNativeId(u.address)).to.be.true; }).then(done, done); }); }); describe('#findOneAndUpdate()', function() { it('should load and update a single object from the collection', function(done) { let data = getData1(); data.save().then(function() { validateId(data); return Data.findOneAndUpdate({number: 1}, {source: 'wired'}); }).then(function(d) { validateId(d); expect(d.number).to.equal(1); expect(d.source).to.equal('wired'); }).then(done, done); }); it('should insert a single object to the collection', function(done) { Data.findOne({number: 1}).then(function(d) { expect(d).to.be.null; return Data.findOneAndUpdate({number: 1}, {number: 1}, {upsert: true}); }).then(function(data) { validateId(data); expect(data.number).to.equal(1); return Data.findOne({number: 1}); }).then(function(d) { validateId(d); expect(d.number).to.equal(1); }).then(done, done); }); }); describe('#findOneAndDelete()', function() { it('should load and delete a single object from the collection', function(done) { let data = getData1(); data.save().then(function() { validateId(data); return Data.count({ number: 1 }); }).then(function(count) { expect(count).to.be.equal(1); return Data.findOneAndDelete({number: 1}); }).then(function(numDeleted) { expect(numDeleted).to.equal(1); return Data.count({ number: 1 }); }).then(function(count) { expect(count).to.equal(0); }).then(done, done); }); }); describe('#find()', function() { class City extends Document { constructor() { super(); this.name = String; this.population = Number; } static collectionName() { return 'cities'; } } var Springfield, SouthPark, Quahog; beforeEach(function(done) { Springfield = City.create({ name: 'Springfield', population: 30720 }); SouthPark = City.create({ name: 'South Park', population: 4388 }); Quahog = City.create({ name: 'Quahog', population: 800 }); Promise.all([Springfield.save(), SouthPark.save(), Quahog.save()]) .then(function() { validateId(Springfield); validateId(SouthPark); validateId(Quahog); done(); }); }); it('should load multiple objects from the collection', function(done) { City.find({}).then(function(cities) { expect(cities).to.have.length(3); validateId(cities[0]); validateId(cities[1]); validateId(cities[2]); }).then(done, done); }); it('should load all objects when query is not provided', function(done) { City.find().then(function(cities) { expect(cities).to.have.length(3); validateId(cities[0]); validateId(cities[1]); validateId(cities[2]); }).then(done, done); }); it('should sort results in ascending order', function(done) { City.find({}, {sort: 'population'}).then(function(cities) { expect(cities).to.have.length(3); validateId(cities[0]); validateId(cities[1]); validateId(cities[2]); expect(cities[0].population).to.be.equal(800); expect(cities[1].population).to.be.equal(4388); expect(cities[2].population).to.be.equal(30720); }).then(done, done); }); it('should sort results in descending order', function(done) { City.find({}, {sort: '-population'}).then(function(cities) { expect(cities).to.have.length(3); validateId(cities[0]); validateId(cities[1]); validateId(cities[2]); expect(cities[0].population).to.be.equal(30720); expect(cities[1].population).to.be.equal(4388); expect(cities[2].population).to.be.equal(800); }).then(done, done); }); it('should sort results using multiple keys', function(done) { let AlphaVille = City.create({ name: 'Alphaville', population: 4388 }); let BetaTown = City.create({ name: 'Beta Town', population: 4388 }); Promise.all([AlphaVille.save(), BetaTown.save()]).then(function() { return City.find({}, {sort: ['population', '-name']}); }).then(function(cities) { expect(cities).to.have.length(5); validateId(cities[0]); validateId(cities[1]); validateId(cities[2]); validateId(cities[3]); validateId(cities[4]); expect(cities[0].population).to.be.equal(800); expect(cities[0].name).to.be.equal('Quahog'); expect(cities[1].population).to.be.equal(4388); expect(cities[1].name).to.be.equal('South Park'); expect(cities[2].population).to.be.equal(4388); expect(cities[2].name).to.be.equal('Beta Town'); expect(cities[3].population).to.be.equal(4388); expect(cities[3].name).to.be.equal('Alphaville'); expect(cities[4].population).to.be.equal(30720); expect(cities[4].name).to.be.equal('Springfield'); }).then(done, done); }); it('should limit number of results returned', function(done) { City.find({}, {limit: 2}).then(function(cities) { expect(cities).to.have.length(2); validateId(cities[0]); validateId(cities[1]); }).then(done, done); }); it('should skip given number of results', function(done) { City.find({}, {sort: 'population', skip: 1}).then(function(cities) { expect(cities).to.have.length(2); validateId(cities[0]); validateId(cities[1]); expect(cities[0].population).to.be.equal(4388); expect(cities[1].population).to.be.equal(30720); }).then(done, done); }); it('should populate all fields', function(done) { let address = Address.create({ street: '123 Fake St.', city: 'Cityville', zipCode: 12345 }); let dog = Pet.create({ type: 'dog', name: 'Fido', }); let user1 = User.create({ firstName: 'Billy', lastName: 'Bob', pet: dog, address: address }); let user2 = User.create({ firstName: 'Sally', lastName: 'Bob', pet: dog, address: address }); Promise.all([address.save(), dog.save()]).then(function() { validateId(address); validateId(dog); return Promise.all([user1.save(), user2.save()]); }).then(function() { validateId(user1); validateId(user2); return User.find({}, {populate: true}); }).then(function(users) { expect(users[0].pet).to.be.an.instanceof(Pet); expect(users[0].address).to.be.an.instanceof(Address); expect(users[1].pet).to.be.an.instanceof(Pet); expect(users[1].address).to.be.an.instanceof(Address); }).then(done, done); }); it('should not populate any fields', function(done) { let address = Address.create({ street: '123 Fake St.', city: 'Cityville', zipCode: 12345 }); let dog = Pet.create({ type: 'dog', name: 'Fido', }); let user1 = User.create({ firstName: 'Billy', lastName: 'Bob', pet: dog, address: address }); let user2 = User.create({ firstName: 'Sally', lastName: 'Bob', pet: dog, address: address }); Promise.all([address.save(), dog.save()]).then(function() { validateId(address); validateId(dog); return Promise.all([user1.save(), user2.save()]); }).then(function() { validateId(user1); validateId(user2); return User.find({}, {populate: false}); }).then(function(users) { expect(isNativeId(users[0].pet)).to.be.true; expect(isNativeId(users[0].address)).to.be.true; expect(isNativeId(users[1].pet)).to.be.true; expect(isNativeId(users[1].address)).to.be.true; }).then(done, done); }); it('should populate specified fields', function(done) { let address = Address.create({ street: '123 Fake St.', city: 'Cityville', zipCode: 12345 }); let dog = Pet.create({ type: 'dog', name: 'Fido', }); let user1 = User.create({ firstName: 'Billy', lastName: 'Bob', pet: dog, address: address }); let user2 = User.create({ firstName: 'Sally', lastName: 'Bob', pet: dog, address: address }); Promise.all([address.save(), dog.save()]).then(function() { validateId(address); validateId(dog); return Promise.all([user1.save(), user2.save()]); }).then(function() { validateId(user1); validateId(user2); return User.find({}, {populate: ['pet']}); }).then(function(users) { expect(users[0].pet).to.be.an.instanceof(Pet); expect(isNativeId(users[0].address)).to.be.true; expect(users[1].pet).to.be.an.instanceof(Pet); expect(isNativeId(users[1].address)).to.be.true; }).then(done, done); }); }); describe('#count()', function() { it('should return 0 objects from the collection', function(done) { let data1 = getData1(); let data2 = getData2(); Promise.all([data1.save(), data2.save()]).then(function() { validateId(data1); validateId(data2); return Data.count({ number: 3 }); }).then(function(count) { expect(count).to.be.equal(0); }).then(done, done); }); it('should return 2 matching objects from the collection', function(done) { let data1 = getData1(); let data2 = getData2(); Promise.all([data1.save(), data2.save()]).then(function() { validateId(data1); validateId(data2); return Data.count({}); }).then(function(count) { expect(count).to.be.equal(2); }).then(done, done); }); }); describe('#delete()', function() { it('should remove instance from the collection', function(done) { let data = getData1(); data.save().then(function() { validateId(data); return data.delete(); }).then(function(numDeleted) { expect(numDeleted).to.be.equal(1); return Data.findOne({item:99}); }).then(function(d) { expect(d).to.be.null; }).then(done, done); }); }); describe('#deleteOne()', function() { it('should remove the object from the collection', function(done) { let data = getData1(); data.save().then(function() { validateId(data); return Data.deleteOne({number: 1}); }).then(function(numDeleted) { expect(numDeleted).to.be.equal(1); return Data.findOne({number: 1}); }).then(function(d) { expect(d).to.be.null; }).then(done, done); }); }); describe('#deleteMany()', function() { it('should remove multiple objects from the collection', function(done) { let data1 = getData1(); let data2 = getData2(); Promise.all([data1.save(), data2.save()]).then(function() { validateId(data1); validateId(data2); return Data.deleteMany({}); }).then(function(numDeleted) { expect(numDeleted).to.be.equal(2); return Data.find({}); }).then(function(datas) { expect(datas).to.have.length(0); }).then(done, done); }); it('should remove all objects when query is not provided', function(done) { let data1 = getData1(); let data2 = getData2(); Promise.all([data1.save(), data2.save()]).then(function() { validateId(data1); validateId(data2); return Data.deleteMany(); }).then(function(numDeleted) { expect(numDeleted).to.be.equal(2); return Data.find({}); }).then(function(datas) { expect(datas).to.have.length(0); }).then(done, done); }); }); describe('#clearCollection()', function() { it('should remove all objects from the collection', function(done) { let data1 = getData1(); let data2 = getData2(); Promise.all([data1.save(), data2.save()]).then(function() { validateId(data1); validateId(data2); return Data.clearCollection(); }).then(function() { return Data.find(); }).then(function(datas) { expect(datas).to.have.length(0); }).then(done, done); }); }); });