camo
Advanced tools
Comparing version 0.2.1 to 0.3.0
@@ -0,1 +1,7 @@ | ||
## 0.3.0 (2015-06-18) | ||
Features: | ||
- Added support for MongoDB using [node-mongodb-native](https://www.npmjs.com/package/mongodb) as the backend. | ||
- Added `.toCanonicalId()` and `.isNativeId()` to `DatabaseClient` and its child classes. | ||
## 0.2.1 (2015-06-17) | ||
@@ -2,0 +8,0 @@ |
@@ -52,2 +52,10 @@ "use strict"; | ||
toCanonicalId(id) { | ||
throw new TypeError('You must override toCanonicalId.'); | ||
} | ||
isNativeId(value) { | ||
throw new TypeError('You must override isNativeId.'); | ||
} | ||
driver() { | ||
@@ -54,0 +62,0 @@ throw new TypeError('You must override driver.'); |
@@ -5,54 +5,161 @@ "use strict"; | ||
var fs = require('fs'); | ||
var _ = require('lodash'); | ||
var MDBClient = require('mongodb').MongoClient; | ||
var ObjectId = require('mongodb').ObjectId; | ||
var DatabaseClient = require('./client'); | ||
var MDBClient = require('mongodb').MongoClient; | ||
class MongoClient extends DatabaseClient { | ||
constructor(url, mongo) { | ||
super(url); | ||
constructor(url, mongo) { | ||
super(url); | ||
this._mongo = mongo; | ||
} | ||
this._mongo = mongo; | ||
} | ||
save(collection, query, values) { | ||
// Mongo | ||
// Use updateOne | ||
save(collection, id, values) { | ||
var that = this; | ||
return new Promise(function(resolve, reject) { | ||
var db = that._mongo.collection(collection); | ||
// TODO: I'd like to just use update with upsert:true, but I'm | ||
// note sure how the query will work if id == null. Seemed to | ||
// have some problems before with passing null ids. | ||
if (id === null) { | ||
db.insertOne(values, function(error, result) { | ||
if (error) return reject(error); | ||
if (!result.hasOwnProperty('insertedId') || result.insertedId === null) { | ||
return reject(new Error('Save failed to generate ID for object.')); | ||
} | ||
return resolve(result.insertedId); | ||
}); | ||
} else { | ||
db.updateOne({ _id: id }, { $set: values }, function(error, result) { | ||
if (error) return reject(error); | ||
return resolve(); | ||
}); | ||
} | ||
}); | ||
} | ||
delete(collection) { | ||
// Mongo | ||
// Use deleteOne | ||
delete(collection, id) { | ||
var that = this; | ||
return new Promise(function(resolve, reject) { | ||
if (id === null) resolve(0); | ||
var db = that._mongo.collection(collection); | ||
db.deleteOne({ _id: id }, {w:1}, function (error, result) { | ||
if (error) return reject(error); | ||
return resolve(result.deletedCount); | ||
}); | ||
}); | ||
} | ||
static deleteOne(collection, query) { | ||
// Mongo | ||
// Use deleteOne | ||
deleteOne(collection, query) { | ||
var that = this; | ||
return new Promise(function(resolve, reject) { | ||
var db = that._mongo.collection(collection); | ||
db.deleteOne(query, {w:1}, function (error, result) { | ||
if (error) return reject(error); | ||
return resolve(result.deletedCount); | ||
}); | ||
}); | ||
} | ||
static deleteMany(collection, query) { | ||
// Mongo | ||
// Use deleteMany | ||
deleteMany(collection, query) { | ||
var that = this; | ||
return new Promise(function(resolve, reject) { | ||
var db = that._mongo.collection(collection); | ||
db.deleteMany(query, {w:1}, function (error, result) { | ||
if (error) return reject(error); | ||
return resolve(result.deletedCount); | ||
}); | ||
}); | ||
} | ||
static loadOne(collection, query) { | ||
// Use findOne | ||
loadOne(collection, query) { | ||
var that = this; | ||
return new Promise(function(resolve, reject) { | ||
var db = that._mongo.collection(collection); | ||
db.findOne(query, function (error, doc) { | ||
if (error) return reject(error); | ||
return resolve(doc); | ||
}); | ||
}); | ||
} | ||
static loadMany(collection, query) { | ||
// Use find | ||
loadMany(collection, query) { | ||
var that = this; | ||
return new Promise(function(resolve, reject) { | ||
var db = that._mongo.collection(collection); | ||
db.find(query).toArray(function (error, docs) { | ||
if (error) return reject(error); | ||
return resolve(docs); | ||
}); | ||
}); | ||
} | ||
count(collection, query) { | ||
var that = this; | ||
return new Promise(function(resolve, reject) { | ||
var db = that._mongo.collection(collection); | ||
db.count(query, function (error, count) { | ||
if (error) return reject(error); | ||
return resolve(count); | ||
}); | ||
}); | ||
} | ||
static connect(url) { | ||
return new Promise(function(resolve, reject) { | ||
MDBClient.connect(url, function(error, client) { | ||
if (error) return reject(error); | ||
return resolve(new MongoClient(url, client)); | ||
}); | ||
}); | ||
} | ||
return new Promise(function(resolve, reject) { | ||
MDBClient.connect(url, function(error, client) { | ||
if (error) return reject(error); | ||
return resolve(new MongoClient(url, client)); | ||
}); | ||
}); | ||
} | ||
close() { | ||
return this._mongo.close(); | ||
var that = this; | ||
return new Promise(function(resolve, reject) { | ||
that._mongo.close(function(error) { | ||
if (error) return reject(error); | ||
return resolve(); | ||
}); | ||
}); | ||
} | ||
clearCollection(collection) { | ||
var that = this; | ||
return new Promise(function(resolve, reject) { | ||
that._mongo.dropCollection(collection, function(error, result) { | ||
if (error) return reject(error); | ||
return resolve(); | ||
}); | ||
}); | ||
} | ||
dropDatabase() { | ||
var that = this; | ||
return new Promise(function(resolve, reject) { | ||
that._mongo.dropDatabase(function(error, result) { | ||
if (error) return reject(error); | ||
return resolve(); | ||
}); | ||
}); | ||
} | ||
toCanonicalId(id) { | ||
return id.toString(); | ||
} | ||
isNativeId(value) { | ||
return value instanceof ObjectId; | ||
} | ||
driver() { | ||
return this._mongo; | ||
} | ||
} | ||
module.exports = MongoClient; |
@@ -58,3 +58,4 @@ "use strict"; | ||
if (error) return reject(error); | ||
return resolve(result); | ||
return resolve(result._id); | ||
}); | ||
@@ -145,2 +146,4 @@ } else { | ||
// TODO: Load all data upfront or on-demand? | ||
// Maybe give user the option to load upfront. | ||
// But which should we do by default? | ||
/*fs.readdir(dbFolderPath, function(error, files) { | ||
@@ -158,4 +161,4 @@ files.forEach(function(file) { | ||
});*/ | ||
global.CLIENT = new NeDbClient(dbFolderPath, collections); | ||
resolve(global.CLIENT); | ||
//global.CLIENT = new NeDbClient(dbFolderPath, collections); | ||
resolve(new NeDbClient(dbFolderPath, collections)); | ||
}); | ||
@@ -199,2 +202,11 @@ } | ||
toCanonicalId(id) { | ||
return id; | ||
} | ||
// Native ids are the same as NeDB ids | ||
isNativeId(value) { | ||
return true; | ||
} | ||
driver() { | ||
@@ -201,0 +213,0 @@ return this._collections; |
var NeDbClient = require('./clients/nedbclient'); | ||
var MongoClient = require('mongodb').MongoClient; | ||
var MongoClient = require('./clients/mongoclient'); | ||
var database = null; | ||
exports.database = database; | ||
exports.connect = function(url) { | ||
@@ -12,3 +8,3 @@ if (url.indexOf('nedb://') > -1) { | ||
return NeDbClient.connect(url).then(function(db) { | ||
database = db; | ||
global.CLIENT = db; | ||
return db; | ||
@@ -18,10 +14,5 @@ }); | ||
// url example: 'mongodb://localhost:27017/myproject' | ||
return new Promise(function(resolve, reject) { | ||
MongoClient.connect(url, function(error, db) { | ||
if (error) { | ||
return reject(error); | ||
} | ||
database = db; | ||
resolve(db); | ||
}); | ||
return MongoClient.connect(url).then(function(db) { | ||
global.CLIENT = db; | ||
return db; | ||
}); | ||
@@ -28,0 +19,0 @@ } else { |
@@ -81,3 +81,3 @@ "use strict"; | ||
this._schema = { // Defines document structure/properties | ||
_id: { type: String } | ||
_id: { type: String }, // Native ID to backend database | ||
}; | ||
@@ -239,5 +239,7 @@ this._values = {}; // Contains values for properties defined in schema | ||
}).then(function(data) { | ||
// TODO: Need to return this so if its a promise it'll work | ||
that.postValidate(); | ||
return data; | ||
}).then(function(data) { | ||
// TODO: Need to return this so if its a promise it'll work | ||
that.preSave(); | ||
@@ -247,9 +249,9 @@ return data; | ||
return DB().save(that._meta.collection, that.id, data); | ||
}).then(function(data) { | ||
that.postSave(); | ||
return data; | ||
}).then(function(data) { | ||
}).then(function(id) { | ||
if (that.id === null) { | ||
that.id = data._id; | ||
that.id = id; | ||
} | ||
}).then(function() { | ||
return that.postSave(); | ||
}).then(function() { | ||
return that; | ||
@@ -419,3 +421,5 @@ }).catch(function(error) { | ||
} | ||
else if (isString(anInstance[key]) && isModel(anInstance._schema[key].type)) { | ||
// Handle anInstance[key] being a string id, a native id, or a Document instance | ||
else if ((isString(anInstance[key]) || DB().isNativeId(anInstance[key])) && | ||
isModel(anInstance._schema[key].type)) { | ||
keys.push(key); | ||
@@ -439,3 +443,3 @@ } | ||
documents.forEach(function(d) { | ||
ids[k][d.id] = [].concat(d[k]); // Handles values and arrays | ||
ids[k][DB().toCanonicalId(d.id)] = [].concat(d[k]); // Handles values and arrays | ||
@@ -455,6 +459,8 @@ // Also, initialize document member arrays | ||
_.keys(ids[key]).forEach(function(k) { | ||
// Before adding to list, we convert id to the | ||
// backend database's native ID format. | ||
keyIds = keyIds.concat(ids[key][k]); | ||
}); | ||
// Handle array of references (ex: [MyObject]) | ||
// Handle array of references (like [MyObject]) | ||
var type = null; | ||
@@ -467,3 +473,3 @@ if (isArray(anInstance._schema[key].type)) { | ||
// Bulk load objects | ||
// Bulk load dereferences | ||
var p = type.loadMany({ '_id': { $in: keyIds } }, { populate: false }) | ||
@@ -476,7 +482,13 @@ .then(function(dereferences) { | ||
// ...if this dereference is in the array... | ||
if (ids[key][k].indexOf(deref.id) > -1) { | ||
var cIds = []; | ||
ids[key][k].forEach(function(i) { | ||
cIds.push(DB().toCanonicalId(i)); | ||
}); | ||
if (cIds.indexOf(DB().toCanonicalId(deref.id)) > -1) { | ||
// ...find the document it belongs to... | ||
documents.forEach(function(doc) { | ||
// ...and make the assignment (value or array-based). | ||
if (doc.id === k) { | ||
if (DB().toCanonicalId(doc.id) === k) { | ||
if (isArray(anInstance._schema[key].type)) { | ||
@@ -483,0 +495,0 @@ doc[key].push(deref); |
{ | ||
"name" : "camo", | ||
"version" : "0.2.1", | ||
"version" : "0.3.0", | ||
"description" : "A lightweight ES6 ODM for Mongo-like databases.", | ||
@@ -5,0 +5,0 @@ "author": { |
@@ -16,2 +16,3 @@ "use strict"; | ||
var url = 'nedb://' + __dirname + '/nedbdata'; | ||
//var url = 'mongodb://localhost/camo_test'; | ||
var database = null; | ||
@@ -22,3 +23,3 @@ | ||
database = db; | ||
return database.clearCollection('data'); | ||
return database.dropDatabase(); | ||
}).then(function() { | ||
@@ -34,13 +35,7 @@ return done(); | ||
afterEach(function(done) { | ||
database.clearCollection('data').then(function() { | ||
database.driver().data.persistence.compactDatafile(); | ||
}).then(done, done); | ||
database.dropDatabase().then(function() {}).then(done, done); | ||
}); | ||
after(function(done) { | ||
database.dropDatabase().then(function() { | ||
_.keys(database.driver()).forEach(function(key) { | ||
database.driver()[key].persistence.compactDatafile(); | ||
}); | ||
}).then(done, done); | ||
database.dropDatabase().then(function() {}).then(done, done); | ||
}); | ||
@@ -53,5 +48,5 @@ | ||
data.save().then(function(d) { | ||
validateId(d); | ||
validateData1(d); | ||
data.save().then(function() { | ||
validateId(data); | ||
validateData1(data); | ||
}).then(done, done); | ||
@@ -66,4 +61,4 @@ }); | ||
data.save().then(function(d) { | ||
validateId(d); | ||
data.save().then(function() { | ||
validateId(data); | ||
return Data.loadOne({item:99}); | ||
@@ -83,5 +78,5 @@ }).then(function(d) { | ||
Promise.all([data1.save(), data2.save()]).then(function(datas) { | ||
validateId(datas[0]); | ||
validateId(datas[1]); | ||
Promise.all([data1.save(), data2.save()]).then(function() { | ||
validateId(data1); | ||
validateId(data2); | ||
return Data.loadMany({}); | ||
@@ -110,5 +105,5 @@ }).then(function(datas) { | ||
Promise.all([data1.save(), data2.save()]).then(function(datas) { | ||
validateId(datas[0]); | ||
validateId(datas[1]); | ||
Promise.all([data1.save(), data2.save()]).then(function() { | ||
validateId(data1); | ||
validateId(data2); | ||
return Data.count({ number: 3 }); | ||
@@ -125,5 +120,5 @@ }).then(function(count) { | ||
Promise.all([data1.save(), data2.save()]).then(function(datas) { | ||
validateId(datas[0]); | ||
validateId(datas[1]); | ||
Promise.all([data1.save(), data2.save()]).then(function() { | ||
validateId(data1); | ||
validateId(data2); | ||
return Data.count({}); | ||
@@ -141,5 +136,5 @@ }).then(function(count) { | ||
data.save().then(function(d) { | ||
validateId(d); | ||
return d.delete(); | ||
data.save().then(function() { | ||
validateId(data); | ||
return data.delete(); | ||
}).then(function(numDeleted) { | ||
@@ -159,4 +154,4 @@ expect(numDeleted).to.be.equal(1); | ||
data.save().then(function(d) { | ||
validateId(d); | ||
data.save().then(function() { | ||
validateId(data); | ||
return Data.deleteOne({number: 1}); | ||
@@ -178,5 +173,5 @@ }).then(function(numDeleted) { | ||
Promise.all([data1.save(), data2.save()]).then(function(datas) { | ||
validateId(datas[0]); | ||
validateId(datas[1]); | ||
Promise.all([data1.save(), data2.save()]).then(function() { | ||
validateId(data1); | ||
validateId(data2); | ||
return Data.deleteMany({}); | ||
@@ -198,5 +193,5 @@ }).then(function(numDeleted) { | ||
Promise.all([data1.save(), data2.save()]).then(function(datas) { | ||
validateId(datas[0]); | ||
validateId(datas[1]); | ||
Promise.all([data1.save(), data2.save()]).then(function() { | ||
validateId(data1); | ||
validateId(data2); | ||
return Data.clearCollection(); | ||
@@ -203,0 +198,0 @@ }).then(function() { |
@@ -8,2 +8,3 @@ "use strict"; | ||
var Document = require('../index').Document; | ||
var isModel = require('../lib/validate').isModel; | ||
var Data = require('./data'); | ||
@@ -18,2 +19,3 @@ var getData1 = require('./util').data1; | ||
var url = 'nedb://' + __dirname + '/nedbdata'; | ||
//var url = 'mongodb://localhost/camo_test'; | ||
var database = null; | ||
@@ -65,7 +67,7 @@ | ||
data.ref.save().then(function(d) { | ||
validateId(d); | ||
data.ref.save().then(function() { | ||
validateId(data.ref); | ||
return data.save(); | ||
}).then(function(d) { | ||
validateId(d); | ||
}).then(function() { | ||
validateId(data); | ||
return ReferencerModel.loadOne({ num: 1 }); | ||
@@ -104,10 +106,10 @@ }).then(function(d) { | ||
data.refs[0].save().then(function(d) { | ||
validateId(d); | ||
data.refs[0].save().then(function() { | ||
validateId(data.refs[0]); | ||
return data.refs[1].save(); | ||
}).then(function(d) { | ||
validateId(d); | ||
}).then(function() { | ||
validateId(data.refs[1]); | ||
return data.save(); | ||
}).then(function(d) { | ||
validateId(d); | ||
}).then(function() { | ||
validateId(data); | ||
return ReferencerModel.loadOne({ num: 1 }); | ||
@@ -151,9 +153,9 @@ }).then(function(d) { | ||
boss.save().then(function(b) { | ||
validateId(b); | ||
boss.save().then(function() { | ||
validateId(boss); | ||
return employee.save(); | ||
}).then(function(e) { | ||
validateId(e); | ||
validateId(e.boss); | ||
}).then(function() { | ||
validateId(employee); | ||
validateId(employee.boss); | ||
@@ -163,6 +165,6 @@ boss.employees.push(employee); | ||
return boss.save(); | ||
}).then(function(b) { | ||
validateId(b); | ||
validateId(b.employees[0]); | ||
validateId(b.employees[0].boss); | ||
}).then(function() { | ||
validateId(boss); | ||
validateId(boss.employees[0]); | ||
validateId(boss.employees[0].boss); | ||
@@ -184,3 +186,4 @@ return Boss.loadOne({ salary: 10000000 }); | ||
// to the employee is still the ID. | ||
expect(b.employees[0].boss).to.be.a('string'); | ||
expect(b.employees[0].boss).to.not.be.null; | ||
expect(!isModel(b.employees[0].boss)).to.be.true; | ||
}).then(done, done); | ||
@@ -201,5 +204,5 @@ }); | ||
data.save().then(function(d) { | ||
validateId(d); | ||
expect(d.str).to.be.equal('hello'); | ||
data.save().then(function() { | ||
validateId(data); | ||
expect(data.str).to.be.equal('hello'); | ||
}).then(done, done); | ||
@@ -220,5 +223,5 @@ }); | ||
data.save().then(function(d) { | ||
validateId(d); | ||
expect(d.num).to.be.equal(26); | ||
data.save().then(function() { | ||
validateId(data); | ||
expect(data.num).to.be.equal(26); | ||
}).then(done, done); | ||
@@ -239,5 +242,5 @@ }); | ||
data.save().then(function(d) { | ||
validateId(d); | ||
expect(d.bool).to.be.equal(true); | ||
data.save().then(function() { | ||
validateId(data); | ||
expect(data.bool).to.be.equal(true); | ||
}).then(done, done); | ||
@@ -259,5 +262,5 @@ }); | ||
data.save().then(function(d) { | ||
validateId(d); | ||
expect(d.date).to.be.equal(date); | ||
data.save().then(function() { | ||
validateId(data); | ||
expect(data.date).to.be.equal(date); | ||
}).then(done, done); | ||
@@ -278,6 +281,6 @@ }); | ||
data.save().then(function(d) { | ||
validateId(d); | ||
expect(d.obj.hi).to.not.be.null; | ||
expect(d.obj.hi).to.be.equal('bye'); | ||
data.save().then(function() { | ||
validateId(data); | ||
expect(data.obj.hi).to.not.be.null; | ||
expect(data.obj.hi).to.be.equal('bye'); | ||
}).then(done, done); | ||
@@ -298,5 +301,5 @@ }); | ||
data.save().then(function(d) { | ||
validateId(d); | ||
expect(d.buf.toString('ascii')).to.be.equal('hello'); | ||
data.save().then(function() { | ||
validateId(data); | ||
expect(data.buf.toString('ascii')).to.be.equal('hello'); | ||
}).then(done, done); | ||
@@ -317,8 +320,8 @@ }); | ||
data.save().then(function(d) { | ||
validateId(d); | ||
expect(d.arr).to.have.length(3); | ||
expect(d.arr).to.include(1); | ||
expect(d.arr).to.include('number'); | ||
expect(d.arr).to.include(true); | ||
data.save().then(function() { | ||
validateId(data); | ||
expect(data.arr).to.have.length(3); | ||
expect(data.arr).to.include(1); | ||
expect(data.arr).to.include('number'); | ||
expect(data.arr).to.include(true); | ||
}).then(done, done); | ||
@@ -339,8 +342,8 @@ }); | ||
data.save().then(function(d) { | ||
validateId(d); | ||
expect(d.arr).to.have.length(3); | ||
expect(d.arr).to.include('1'); | ||
expect(d.arr).to.include('2'); | ||
expect(d.arr).to.include('3'); | ||
data.save().then(function() { | ||
validateId(data); | ||
expect(data.arr).to.have.length(3); | ||
expect(data.arr).to.include('1'); | ||
expect(data.arr).to.include('2'); | ||
expect(data.arr).to.include('3'); | ||
}).then(done, done); | ||
@@ -361,3 +364,3 @@ }); | ||
data.save().then(function(d) { | ||
data.save().then(function() { | ||
expect.fail(null, Error, 'Expected error, but got none.'); | ||
@@ -381,3 +384,3 @@ }).catch(function(error) { | ||
data.save().then(function(d) { | ||
data.save().then(function() { | ||
expect.fail(null, Error, 'Expected error, but got none.'); | ||
@@ -395,5 +398,5 @@ }).catch(function(error) { | ||
data.save().then(function(d) { | ||
validateId(d); | ||
expect(d.source).to.be.equal('reddit'); | ||
data.save().then(function() { | ||
validateId(data); | ||
expect(data.source).to.be.equal('reddit'); | ||
}).then(done, done); | ||
@@ -406,5 +409,5 @@ }); | ||
data.save().then(function(d) { | ||
validateId(d); | ||
expect(d.date).to.be.lessThan(Date.now()); | ||
data.save().then(function() { | ||
validateId(data); | ||
expect(data.date).to.be.lessThan(Date.now()); | ||
}).then(done, done); | ||
@@ -420,5 +423,5 @@ }); | ||
data.save().then(function(d) { | ||
validateId(d); | ||
expect(d.source).to.be.equal('wired'); | ||
data.save().then(function() { | ||
validateId(data); | ||
expect(data.source).to.be.equal('wired'); | ||
}).then(done, done); | ||
@@ -432,3 +435,3 @@ }); | ||
data.save().then(function(d) { | ||
data.save().then(function() { | ||
expect.fail(null, Error, 'Expected error, but got none.'); | ||
@@ -447,5 +450,5 @@ }).catch(function(error) { | ||
data.save().then(function(d) { | ||
validateId(d); | ||
expect(d.item).to.be.equal(1); | ||
data.save().then(function() { | ||
validateId(data); | ||
expect(data.item).to.be.equal(1); | ||
}).then(done, done); | ||
@@ -459,5 +462,5 @@ }); | ||
data.save().then(function(d) { | ||
validateId(d); | ||
expect(d.item).to.be.equal(0); | ||
data.save().then(function() { | ||
validateId(data); | ||
expect(data.item).to.be.equal(0); | ||
}).then(done, done); | ||
@@ -471,3 +474,3 @@ }); | ||
data.save().then(function(d) { | ||
data.save().then(function() { | ||
expect.fail(null, Error, 'Expected error, but got none.'); | ||
@@ -486,5 +489,5 @@ }).catch(function(error) { | ||
data.save().then(function(d) { | ||
validateId(d); | ||
expect(d.item).to.be.equal(99); | ||
data.save().then(function() { | ||
validateId(data); | ||
expect(data.item).to.be.equal(99); | ||
}).then(done, done); | ||
@@ -498,5 +501,5 @@ }); | ||
data.save().then(function(d) { | ||
validateId(d); | ||
expect(d.item).to.be.equal(100); | ||
data.save().then(function() { | ||
validateId(data); | ||
expect(data.item).to.be.equal(100); | ||
}).then(done, done); | ||
@@ -510,3 +513,3 @@ }); | ||
data.save().then(function(d) { | ||
data.save().then(function() { | ||
expect.fail(null, Error, 'Expected error, but got none.'); | ||
@@ -562,4 +565,4 @@ }).catch(function(error) { | ||
person.save().then(function(p) { | ||
validateId(p); | ||
person.save().then(function() { | ||
validateId(person); | ||
@@ -577,3 +580,5 @@ // Pre/post save and validate should be called | ||
return person.delete(); | ||
}).then(function() { | ||
}).then(function(numDeleted) { | ||
expect(numDeleted).to.be.equal(1); | ||
expect(preDeleteCalled).to.be.equal(true); | ||
@@ -580,0 +585,0 @@ expect(postDeleteCalled).to.be.equal(true); |
@@ -7,4 +7,4 @@ var expect = require('chai').expect; | ||
expect(obj).to.be.a('object'); | ||
expect(obj.id).to.be.a('string'); | ||
expect(obj.id).to.have.length.of.at.least(1); | ||
expect(obj.id.toString()).to.be.a('string'); | ||
expect(obj.id.toString()).to.have.length.of.at.least(1); | ||
}; | ||
@@ -11,0 +11,0 @@ |
75439
1675