From 369eaaa33c3a6b86a3f911fa783ac09c3fb4a421 Mon Sep 17 00:00:00 2001 From: Alec Gibson Date: Wed, 27 May 2020 18:10:05 +0100 Subject: [PATCH] Add support for `mongodb` v3 This change adds support for the current version of the `mongodb` driver, whilst maintaining backwards-compatibility with v2. This change largely follows the corresponding change in `sharedb-mongo`: https://github.com/share/sharedb-mongo/pull/83/ All unit tests are now run against both versions of the driver to ensure compatibility. --- .travis.yml | 9 +- README.md | 11 +- lib/mongo-milestone-db.js | 24 ++- package-lock.json | 110 +++++++++- package.json | 8 +- test/mongo-milestone-db.js | 411 +++++++++++++++++++------------------ 6 files changed, 355 insertions(+), 218 deletions(-) diff --git a/.travis.yml b/.travis.yml index ddcb0f1..2439531 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,18 @@ language: node_js node_js: - - "6" - - "8" + - "12" - "10" + - "8" services: - docker env: - - MONGODB_VERSION="2.6" - - MONGODB_VERSION="3.6" + - MONGODB_VERSION="4.2" - MONGODB_VERSION="4.0" + - MONGODB_VERSION="3.6" + - MONGODB_VERSION="3.4" before_install: - docker run -d -p 127.0.0.1:27017:27017 mongo:$MONGODB_VERSION diff --git a/README.md b/README.md index 7fdf74f..07bd0d3 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ const shareDb = new ShareDB({ milestoneDb: milestoneDb }); ### Mongo -The underlying Mongo database can be configured in a number of ways. This library wraps v2 of the [`mongodb`][2] +The underlying Mongo database can be configured in a number of ways. This library uses the [`mongodb`][2] library, so any configuration that can be used there can be used in this library. Mongo can be configured simply using a connection string and any desired [options][3]: @@ -34,7 +34,7 @@ Mongo can be configured simply using a connection string and any desired [option const milestoneDb = new MongoMilestoneDB('mongodb://localhost:27017/test', { loggerLevel: 'debug' }); ``` -It can also be configured with a callback that provides an instance of a Mongo [`Db` object][4]: +It can also be configured with a callback that provides an instance of a [`MongoClient`][4]: ```javascript const mongodb = require('mongodb'); @@ -59,8 +59,7 @@ const milestoneDb = new MongoMilestoneDB({ #### Intervals By default, ShareDB will save a milestone snapshot with a given frequency. This library defaults to an interval of -1,000, saving milestones when the 1,000th, 2,000th, etc. versions are committed. That default interval can be -configured: +1,000, saving milestones when the 1,000th, 2,000th, etc. versions are committed. That interval can be configured: ```javascript const milestoneDb = new MongoMilestoneDB({ @@ -133,5 +132,5 @@ const milestoneDb = new MongoMilestoneDB({ [1]: https://github.com/share/sharedb [2]: https://mongodb.github.io/node-mongodb-native/ -[3]: http://mongodb.github.io/node-mongodb-native/2.2/api/MongoClient.html#connect -[4]: http://mongodb.github.io/node-mongodb-native/2.2/api/Db.html +[3]: https://mongodb.github.io/node-mongodb-native/3.6/api/MongoClient.html#.connect +[4]: https://mongodb.github.io/node-mongodb-native/3.6/api/MongoClient.html diff --git a/lib/mongo-milestone-db.js b/lib/mongo-milestone-db.js index 5111ede..c44a1df 100644 --- a/lib/mongo-milestone-db.js +++ b/lib/mongo-milestone-db.js @@ -83,7 +83,7 @@ class MongoMilestoneDB extends MilestoneDB { const updatedSnapshot = MongoMilestoneDB._snapshotToDbRepresentation(snapshot); const options = {upsert: true}; - return collection.updateOne(query, updatedSnapshot, options); + return collection.updateOne(query, {$set: updatedSnapshot}, options); }); } @@ -144,14 +144,14 @@ class MongoMilestoneDB extends MilestoneDB { } _close() { - return this._db() - .then((db) => { + return this._client() + .then((client) => { this._mongoPromise = null; - return db.close(); + return client.close(); }); } - _db() { + _client() { if (!this._mongoPromise) { return Promise.reject(new MongoClosedError()); } @@ -159,6 +159,12 @@ class MongoMilestoneDB extends MilestoneDB { return this._mongoPromise; } + _db() { + return this._client().then(client => (MongoMilestoneDB._isLegacyMongoClient(client) + ? client + : client.db())); + } + _collection(collectionName) { let name; let collection; @@ -244,6 +250,14 @@ class MongoMilestoneDB extends MilestoneDB { if (typeof object !== 'object') return object; return Object.assign({}, object); } + + static _isLegacyMongoClient(client) { + // mongodb 2.x connect returns a DB object that also implements the + // functionality of a client, such as `close()`. mongodb 3.x connect + // returns a Client without the `collection()` method + return typeof client.collection === 'function' + && typeof client.close === 'function'; + } } class InvalidCollectionNameError extends Error { diff --git a/package-lock.json b/package-lock.json index 76979b6..6f4d657 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "sharedb-milestone-mongo", - "version": "0.2.0", + "version": "0.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -184,6 +184,48 @@ "tweetnacl": "^0.14.3" } }, + "bl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz", + "integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==", + "dev": true, + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "boom": { "version": "2.10.1", "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", @@ -378,6 +420,12 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, + "denque": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", + "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==", + "dev": true + }, "diff": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", @@ -1258,6 +1306,13 @@ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==" }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "dev": true, + "optional": true + }, "mime-db": { "version": "1.36.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", @@ -1403,6 +1458,39 @@ "require_optional": "~1.0.0" } }, + "mongodb2": { + "version": "npm:mongodb@2.2.36", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.36.tgz", + "integrity": "sha512-P2SBLQ8Z0PVx71ngoXwo12+FiSfbNfGOClAao03/bant5DgLNkOPAck5IaJcEk4gKlQhDEURzfR3xuBG1/B+IA==", + "dev": true, + "requires": { + "es6-promise": "3.2.1", + "mongodb-core": "2.1.20", + "readable-stream": "2.2.7" + } + }, + "mongodb3": { + "version": "npm:mongodb@3.5.7", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.7.tgz", + "integrity": "sha512-lMtleRT+vIgY/JhhTn1nyGwnSMmJkJELp+4ZbrjctrnBxuLbj6rmLuJFz8W2xUzUqWmqoyVxJLYuC58ZKpcTYQ==", + "dev": true, + "requires": { + "bl": "^2.2.0", + "bson": "^1.1.4", + "denque": "^1.4.1", + "require_optional": "^1.0.1", + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" + }, + "dependencies": { + "bson": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz", + "integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q==", + "dev": true + } + } + }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -1702,6 +1790,16 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "dev": true, + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, "semver": { "version": "5.5.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", @@ -1788,6 +1886,16 @@ "amdefine": ">=0.0.4" } }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", + "dev": true, + "optional": true, + "requires": { + "memory-pager": "^1.0.2" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", diff --git a/package.json b/package.json index b1805cb..fe1b8c3 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "sharedb-milestone-mongo", - "version": "0.2.0", + "version": "0.3.0", "description": "MongoDB milestone snapshot database adapter for ShareDB", "main": "lib/index.js", "dependencies": { - "mongodb": "^2.2.36", + "mongodb": "^2.2.36 || ^3.0.0", "sharedb": "1.0.0-beta.18" }, "devDependencies": { @@ -12,7 +12,9 @@ "eslint": "^5.13.0", "expect.js": "^0.3.1", "istanbul": "^0.4.5", - "mocha": "^2.3.3" + "mocha": "^2.3.3", + "mongodb2": "npm:mongodb@^2.2.36", + "mongodb3": "npm:mongodb@^3.0.0" }, "scripts": { "lint": "node_modules/.bin/eslint --ignore-path .gitignore '**/*.js'", diff --git a/test/mongo-milestone-db.js b/test/mongo-milestone-db.js index f973104..59b5b3d 100644 --- a/test/mongo-milestone-db.js +++ b/test/mongo-milestone-db.js @@ -1,252 +1,265 @@ +/* eslint-disable global-require */ const expect = require('expect.js'); -const mongodb = require('mongodb'); const MongoMilestoneDB = require('../lib/mongo-milestone-db'); const SnapshotFactory = require('./factories/snapshot-factory'); const MONGO_URL = process.env.TEST_MONGO_URL || 'mongodb://localhost:27017/test'; -function create(options, callback) { - if (typeof options === 'function') { - callback = options; - options = {}; - } +['mongodb2', 'mongodb3'].forEach((driver) => { + const mongodb = require(driver); - let db; + function create(options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } - options = Object.assign({ - mongo: (shareDbCallback) => { - let mongo; + let db; - mongodb.connect(MONGO_URL) - .then((mongoConnection) => { - mongo = mongoConnection; - return mongo.dropDatabase(); - }) - .then(() => { - shareDbCallback(null, mongo); - callback(null, db, mongo); - }); - }, - }, options); + options = Object.assign({ + mongo: (shareDbCallback) => { + let mongo; + + mongodb.connect(MONGO_URL) + .then((mongoConnection) => { + mongo = mongoConnection; + return MongoMilestoneDB._isLegacyMongoClient(mongo) + ? mongo.dropDatabase() + : mongo.db().dropDatabase(); + }) + .then(() => { + shareDbCallback(null, mongo); + callback(null, db, mongo); + }); + }, + }, options); - db = new MongoMilestoneDB(options); -} + db = new MongoMilestoneDB(options); + } -require('sharedb/test/milestone-db')({create: create}); + describe(`[${ driver } driver]`, () => { + require('sharedb/test/milestone-db')({create: create}); + + describe('MongoMilestoneDB', () => { + describe('with a mongo callback', () => { + let db; + let mongo; + + beforeEach((done) => { + create((error, createdDb, createdMongo) => { + if (error) return done(error); + db = createdDb; + mongo = MongoMilestoneDB._isLegacyMongoClient(createdMongo) + ? createdMongo + : createdMongo.db(); + done(); + }); + }); -describe('MongoMilestoneDB', () => { - describe('with a mongo callback', () => { - let db; - let mongo; - - beforeEach((done) => { - create((error, createdDb, createdMongo) => { - if (error) return done(error); - db = createdDb; - mongo = createdMongo; - done(); - }); - }); + afterEach((done) => { + if (db._mongoPromise) return db.close(done); + done(); + }); - afterEach((done) => { - if (db._mongoPromise) return db.close(done); - done(); - }); + it('overwrites an existing milestone snapshot', (done) => { + const id = 'abc'; + const collection = 'testcollection'; + const version = 1; - it('overwrites an existing milestone snapshot', (done) => { - const id = 'abc'; - const collection = 'testcollection'; - const version = 1; + const snapshot1 = SnapshotFactory.build((snapshot) => { + snapshot.id = id; + snapshot.v = version; + snapshot.data = {foo: 'bar'}; + }); - const snapshot1 = SnapshotFactory.build((snapshot) => { - snapshot.id = id; - snapshot.v = version; - snapshot.data = {foo: 'bar'}; - }); + const snapshot2 = SnapshotFactory.build((snapshot) => { + snapshot.id = id; + snapshot.v = version; + snapshot.data = {foo: 'baz'}; + }); - const snapshot2 = SnapshotFactory.build((snapshot) => { - snapshot.id = id; - snapshot.v = version; - snapshot.data = {foo: 'baz'}; - }); + db.saveMilestoneSnapshot(collection, snapshot1, (saveError1) => { + if (saveError1) return done(saveError1); + db.getMilestoneSnapshot(collection, id, 1, (getError1, retrievedSnapshot1) => { + if (getError1) return done(getError1); + expect(retrievedSnapshot1).to.eql(snapshot1); + db.saveMilestoneSnapshot(collection, snapshot2, (saveError2) => { + if (saveError2) return done(saveError2); + db.getMilestoneSnapshot(collection, id, 1, (getError2, retrievedSnapshot2) => { + if (getError2) return done(getError2); + expect(retrievedSnapshot2).to.eql(snapshot2); + done(); + }); + }); + }); + }); + }); + + it('adds an index for the snapshots', (done) => { + const snapshot = SnapshotFactory.build(); - db.saveMilestoneSnapshot(collection, snapshot1, (saveError1) => { - if (saveError1) return done(saveError1); - db.getMilestoneSnapshot(collection, id, 1, (getError1, retrievedSnapshot1) => { - if (getError1) return done(getError1); - expect(retrievedSnapshot1).to.eql(snapshot1); - db.saveMilestoneSnapshot(collection, snapshot2, (saveError2) => { - if (saveError2) return done(saveError2); - db.getMilestoneSnapshot(collection, id, 1, (getError2, retrievedSnapshot2) => { - if (getError2) return done(getError2); - expect(retrievedSnapshot2).to.eql(snapshot2); + db.saveMilestoneSnapshot('testcollection', snapshot, (saveError) => { + if (saveError) return done(saveError); + mongo.collection('m_testcollection').indexInformation((indexError, indexes) => { + if (indexError) return done(indexError); + expect(indexes.d_1_v_1).to.be.ok(); + expect(indexes['m.mtime_1']).to.be.ok(); done(); }); }); }); - }); - }); - - it('adds an index for the snapshots', (done) => { - const snapshot = SnapshotFactory.build(); - db.saveMilestoneSnapshot('testcollection', snapshot, (saveError) => { - if (saveError) return done(saveError); - mongo.collection('m_testcollection').indexInformation((indexError, indexes) => { - if (indexError) return done(indexError); - expect(indexes.d_1_v_1).to.be.ok(); - expect(indexes['m.mtime_1']).to.be.ok(); - done(); + it('errors when trying to access a database that is closed', (done) => { + db.close((closeError) => { + if (closeError) return done(closeError); + db.getMilestoneSnapshot('testcollection', 'abc', null, (getError) => { + expect(getError).to.be.ok(); + done(); + }); + }); }); - }); - }); - it('errors when trying to access a database that is closed', (done) => { - db.close((closeError) => { - if (closeError) return done(closeError); - db.getMilestoneSnapshot('testcollection', 'abc', null, (getError) => { - expect(getError).to.be.ok(); - done(); + it('defaults to an interval of 1000', () => { + expect(db.interval).to.be(1000); }); }); - }); - it('defaults to an interval of 1000', () => { - expect(db.interval).to.be(1000); - }); - }); - - describe('indexing disabled', () => { - let db; - let mongo; - - beforeEach((done) => { - const options = { - disableIndexCreation: true, - }; - - create(options, (error, createdDb, createdMongo) => { - if (error) return done(error); - db = createdDb; - mongo = createdMongo; - done(); - }); - }); + describe('indexing disabled', () => { + let db; + let mongo; + + beforeEach((done) => { + const options = { + disableIndexCreation: true, + }; + + create(options, (error, createdDb, createdMongo) => { + if (error) return done(error); + db = createdDb; + mongo = MongoMilestoneDB._isLegacyMongoClient(createdMongo) + ? createdMongo + : createdMongo.db(); + done(); + }); + }); - afterEach((done) => { - db.close(done); - }); + afterEach((done) => { + db.close(done); + }); - it('does not add an index for milestones', (done) => { - const snapshot = SnapshotFactory.build(); + it('does not add an index for milestones', (done) => { + const snapshot = SnapshotFactory.build(); - db.saveMilestoneSnapshot('testcollection', snapshot, (saveError) => { - if (saveError) return done(saveError); - mongo.collection('m_testcollection').indexInformation((indexError, indexes) => { - if (indexError) return done(indexError); - expect(indexes.id_1_v_1).not.to.be.ok(); - done(); + db.saveMilestoneSnapshot('testcollection', snapshot, (saveError) => { + if (saveError) return done(saveError); + mongo.collection('m_testcollection').indexInformation((indexError, indexes) => { + if (indexError) return done(indexError); + expect(indexes.id_1_v_1).not.to.be.ok(); + done(); + }); + }); }); }); - }); - }); - describe('connecting using just URL', () => { - let db; + describe('connecting using just URL', () => { + let db; - beforeEach(() => { - db = new MongoMilestoneDB(MONGO_URL); - return db._mongoPromise.then(mongo => mongo.dropDatabase()); - }); + beforeEach(() => { + db = new MongoMilestoneDB(MONGO_URL); + return db._db().then(mongo => mongo.dropDatabase()); + }); - afterEach((done) => { - db.close(done); - }); + afterEach((done) => { + db.close(done); + }); - it('can save and fetch milestones', (done) => { - const collection = 'testcollection'; - const snapshot = SnapshotFactory.build(); + it('can save and fetch milestones', (done) => { + const collection = 'testcollection'; + const snapshot = SnapshotFactory.build(); + const id = snapshot.id; - db.saveMilestoneSnapshot(collection, snapshot, (saveError) => { - if (saveError) return done(saveError); - db.getMilestoneSnapshot(collection, snapshot.id, null, (getError, retrievedSnapshot) => { - if (getError) return done(getError); - expect(retrievedSnapshot).to.eql(snapshot); - done(); + db.saveMilestoneSnapshot(collection, snapshot, (saveError) => { + if (saveError) return done(saveError); + db.getMilestoneSnapshot(collection, id, null, (getError, retrievedSnapshot) => { + if (getError) return done(getError); + expect(retrievedSnapshot).to.eql(snapshot); + done(); + }); + }); }); }); - }); - }); - describe('a mocked out database that throws all the time', () => { - let db; + describe('a mocked out database that throws all the time', () => { + let db; + + beforeEach(() => { + const mockMongo = { + close: () => { + throw new Error('Mock: could not close'); + }, + collection: () => { + throw new Error('Mock: could not get collection'); + }, + }; + + db = new MongoMilestoneDB({ + mongo: (callback) => { + callback(null, mockMongo); + }, + }); + }); - beforeEach(() => { - const mockMongo = { - close: () => { - throw new Error('Mock: could not close'); - }, - collection: () => { - throw new Error('Mock: could not get collection'); - }, - }; - - db = new MongoMilestoneDB({ - mongo: (callback) => { - callback(null, mockMongo); - }, - }); - }); + it('returns a callback with error on close error', (done) => { + db.close((error) => { + expect(error).to.be.ok(); + done(); + }); + }); - it('returns a callback with error on close error', (done) => { - db.close((error) => { - expect(error).to.be.ok(); - done(); - }); - }); + it('emits an error when saving with no callback', (done) => { + const snapshot = SnapshotFactory.build(); + db.on('error', (error) => { + expect(error).to.be.ok(); + done(); + }); - it('emits an error when saving with no callback', (done) => { - const snapshot = SnapshotFactory.build(); - db.on('error', (error) => { - expect(error).to.be.ok(); - done(); + db.saveMilestoneSnapshot('testcollection', snapshot); + }); }); - db.saveMilestoneSnapshot('testcollection', snapshot); - }); - }); - - describe('a bad config', () => { - it('throws when accessing', (done) => { - const options = { - mongo: (callback) => { - callback(new Error('Mock: could not connect')); - }, - }; - - const db = new MongoMilestoneDB(options); - db.getMilestoneSnapshot('testcollection', 'abc', null, (error) => { - expect(error).to.be.ok(); - done(); + describe('a bad config', () => { + it('throws when accessing', (done) => { + const options = { + mongo: (callback) => { + callback(new Error('Mock: could not connect')); + }, + }; + + const db = new MongoMilestoneDB(options); + db.getMilestoneSnapshot('testcollection', 'abc', null, (error) => { + expect(error).to.be.ok(); + done(); + }); + }); }); - }); - }); - describe('overriding the interval', () => { - let db; + describe('overriding the interval', () => { + let db; - beforeEach(() => { - const options = {interval: 100}; - db = new MongoMilestoneDB(MONGO_URL, options); - return db._mongoPromise.then(mongo => mongo.dropDatabase()); - }); + beforeEach(() => { + const options = {interval: 100}; + db = new MongoMilestoneDB(MONGO_URL, options); + return db._mongoPromise.then(mongo => mongo.dropDatabase()); + }); - afterEach((done) => { - db.close(done); - }); + afterEach((done) => { + db.close(done); + }); - it('has its interval overridden', () => { - expect(db.interval).to.be(100); + it('has its interval overridden', () => { + expect(db.interval).to.be(100); + }); + }); }); }); });