diff --git a/services/docstore/app/js/MongoManager.js b/services/docstore/app/js/MongoManager.js index 1d2935428f..64afa94eec 100644 --- a/services/docstore/app/js/MongoManager.js +++ b/services/docstore/app/js/MongoManager.js @@ -1,28 +1,25 @@ const { db, ObjectId } = require('./mongodb') -const logger = require('@overleaf/logger') -const metrics = require('@overleaf/metrics') const Settings = require('@overleaf/settings') -const OError = require('@overleaf/o-error') const Errors = require('./Errors') -const { promisify } = require('util') +const { callbackify } = require('util') const ARCHIVING_LOCK_DURATION_MS = Settings.archivingLockDurationMs -function findDoc(projectId, docId, filter, callback) { - db.docs.findOne( +async function findDoc(projectId, docId, filter) { + const doc = await db.docs.findOne( { _id: new ObjectId(docId.toString()), project_id: new ObjectId(projectId.toString()), }, { projection: filter, - }, - callback + } ) + return doc } -function getProjectsDeletedDocs(projectId, filter, callback) { - db.docs +async function getProjectsDeletedDocs(projectId, filter) { + const docs = await db.docs .find( { project_id: new ObjectId(projectId.toString()), @@ -34,10 +31,11 @@ function getProjectsDeletedDocs(projectId, filter, callback) { limit: Settings.max_deleted_docs, } ) - .toArray(callback) + .toArray() + return docs } -function getProjectsDocs(projectId, options, filter, callback) { +async function getProjectsDocs(projectId, options, filter) { const query = { project_id: new ObjectId(projectId.toString()) } if (!options.include_deleted) { query.deleted = { $ne: true } @@ -48,21 +46,23 @@ function getProjectsDocs(projectId, options, filter, callback) { if (options.limit) { queryOptions.limit = options.limit } - db.docs.find(query, queryOptions).toArray(callback) + const docs = await db.docs.find(query, queryOptions).toArray() + return docs } -function getArchivedProjectDocs(projectId, maxResults, callback) { +async function getArchivedProjectDocs(projectId, maxResults) { const query = { project_id: new ObjectId(projectId.toString()), inS3: true, } - db.docs + const docs = await db.docs .find(query, { projection: { _id: 1 }, limit: maxResults }) - .toArray(callback) + .toArray() + return docs } -function getNonArchivedProjectDocIds(projectId, callback) { - db.docs +async function getNonArchivedProjectDocIds(projectId) { + const docs = await db.docs .find( { project_id: new ObjectId(projectId), @@ -71,27 +71,23 @@ function getNonArchivedProjectDocIds(projectId, callback) { { projection: { _id: 1 } } ) .map(doc => doc._id) - .toArray(callback) + .toArray() + return docs } -function getNonDeletedArchivedProjectDocs(projectId, maxResults, callback) { +async function getNonDeletedArchivedProjectDocs(projectId, maxResults) { const query = { project_id: new ObjectId(projectId.toString()), deleted: { $ne: true }, inS3: true, } - db.docs + const docs = await db.docs .find(query, { projection: { _id: 1 }, limit: maxResults }) - .toArray(callback) + .toArray() + return docs } -function upsertIntoDocCollection( - projectId, - docId, - previousRev, - updates, - callback -) { +async function upsertIntoDocCollection(projectId, docId, previousRev, updates) { if (previousRev) { const update = { $set: updates, @@ -100,51 +96,43 @@ function upsertIntoDocCollection( if (updates.lines || updates.ranges) { update.$inc = { rev: 1 } } - db.docs.updateOne( + const result = await db.docs.updateOne( { _id: new ObjectId(docId), project_id: new ObjectId(projectId), rev: previousRev, }, - update, - (err, result) => { - if (err) return callback(err) - if (result.matchedCount !== 1) { - return callback(new Errors.DocRevValueError()) - } - callback() - } + update ) + if (result.matchedCount !== 1) { + throw new Errors.DocRevValueError() + } } else { - db.docs.insertOne( - { + try { + await db.docs.insertOne({ _id: new ObjectId(docId), project_id: new ObjectId(projectId), rev: 1, ...updates, - }, - err => { - if (err) { - if (err.code === 11000) { - // duplicate doc _id - return callback(new Errors.DocRevValueError()) - } - return callback(err) - } - callback() + }) + } catch (err) { + if (err.code === 11000) { + // duplicate doc _id + throw new Errors.DocRevValueError() + } else { + throw err } - ) + } } } -function patchDoc(projectId, docId, meta, callback) { - db.docs.updateOne( +async function patchDoc(projectId, docId, meta) { + await db.docs.updateOne( { _id: new ObjectId(docId), project_id: new ObjectId(projectId), }, - { $set: meta }, - callback + { $set: meta } ) } @@ -154,9 +142,9 @@ function patchDoc(projectId, docId, meta, callback) { * This will return null if the doc is not found, if it's already archived or * if the lock can't be acquired. */ -function getDocForArchiving(projectId, docId, callback) { +async function getDocForArchiving(projectId, docId) { const archivingUntil = new Date(Date.now() + ARCHIVING_LOCK_DURATION_MS) - db.docs.findOneAndUpdate( + const result = await db.docs.findOneAndUpdate( { _id: new ObjectId(docId), project_id: new ObjectId(projectId), @@ -167,27 +155,21 @@ function getDocForArchiving(projectId, docId, callback) { { projection: { lines: 1, ranges: 1, rev: 1 }, includeResultMetadata: true, - }, - (err, result) => { - if (err) { - return callback(err) - } - callback(null, result.value) } ) + return result.value } /** * Clear the doc contents from Mongo and release the archiving lock */ -function markDocAsArchived(projectId, docId, rev, callback) { - db.docs.updateOne( +async function markDocAsArchived(projectId, docId, rev) { + await db.docs.updateOne( { _id: new ObjectId(docId), rev }, { $set: { inS3: true }, $unset: { lines: 1, ranges: 1, archivingUntil: 1 }, - }, - callback + } ) } @@ -196,7 +178,7 @@ function markDocAsArchived(projectId, docId, rev, callback) { * * This checks that the archived doc's rev matches. */ -function restoreArchivedDoc(projectId, docId, archivedDoc, callback) { +async function restoreArchivedDoc(projectId, docId, archivedDoc) { const query = { _id: new ObjectId(docId), project_id: new ObjectId(projectId), @@ -211,60 +193,34 @@ function restoreArchivedDoc(projectId, docId, archivedDoc, callback) { inS3: true, }, } - db.docs.updateOne(query, update, (err, result) => { - if (err) { - OError.tag(err, 'failed to unarchive doc', { - docId, - rev: archivedDoc.rev, - }) - return callback(err) - } - if (result.matchedCount === 0) { - return callback( - new Errors.DocRevValueError('failed to unarchive doc', { - docId, - rev: archivedDoc.rev, - }) - ) - } - callback() - }) + const result = await db.docs.updateOne(query, update) + + if (result.matchedCount === 0) { + throw new Errors.DocRevValueError('failed to unarchive doc', { + docId, + rev: archivedDoc.rev, + }) + } } -function getDocVersion(docId, callback) { - db.docOps.findOne( - { - doc_id: new ObjectId(docId), - }, +async function getDocVersion(docId) { + const doc = await db.docOps.findOne( + { doc_id: new ObjectId(docId) }, { projection: { version: 1, }, - }, - function (error, doc) { - if (error) { - return callback(error) - } - callback(null, (doc && doc.version) || 0) } ) + return (doc && doc.version) || 0 } -function getDocRev(docId, callback) { - db.docs.findOne( - { - _id: new ObjectId(docId.toString()), - }, - { - projection: { rev: 1 }, - }, - function (err, doc) { - if (err) { - return callback(err) - } - callback(null, doc && doc.rev) - } +async function getDocRev(docId) { + const doc = await db.docs.findOne( + { _id: new ObjectId(docId.toString()) }, + { projection: { rev: 1 } } ) + return doc && doc.rev } /** @@ -273,68 +229,64 @@ function getDocRev(docId, callback) { * Check that the rev of an existing doc is unchanged. If the rev has * changed, return a DocModifiedError. */ -function checkRevUnchanged(doc, callback) { - getDocRev(doc._id, function (err, currentRev) { - if (err) return callback(err) - if (isNaN(currentRev) || isNaN(doc.rev)) { - return callback( - new Errors.DocRevValueError('doc rev is NaN', { - doc_id: doc._id, - rev: doc.rev, - currentRev, - }) - ) - } - if (doc.rev !== currentRev) { - return callback( - new Errors.DocModifiedError('doc rev has changed', { - doc_id: doc._id, - rev: doc.rev, - currentRev, - }) - ) - } - callback() - }) +async function checkRevUnchanged(doc) { + const currentRev = await getDocRev(doc._id) + if (isNaN(currentRev) || isNaN(doc.rev)) { + throw new Errors.DocRevValueError('doc rev is NaN', { + doc_id: doc._id, + rev: doc.rev, + currentRev, + }) + } + if (doc.rev !== currentRev) { + throw new Errors.DocModifiedError('doc rev has changed', { + doc_id: doc._id, + rev: doc.rev, + currentRev, + }) + } } -function destroyProject(projectId, callback) { - db.docs +async function destroyProject(projectId) { + const records = await db.docs .find({ project_id: new ObjectId(projectId) }, { projection: { _id: 1 } }) - .toArray((err, records) => { - const docIds = records.map(r => r._id) - if (err) { - return callback(err) - } - db.docOps.deleteMany({ doc_id: { $in: docIds } }, err => { - if (err) { - return callback(err) - } - db.docs.deleteMany({ project_id: new ObjectId(projectId) }, callback) - }) - }) + .toArray() + const docIds = records.map(r => r._id) + await db.docOps.deleteMany({ doc_id: { $in: docIds } }) + await db.docs.deleteMany({ project_id: new ObjectId(projectId) }) } module.exports = { - findDoc, - getProjectsDeletedDocs, - getProjectsDocs, - getArchivedProjectDocs, - getNonArchivedProjectDocIds, - getNonDeletedArchivedProjectDocs, - upsertIntoDocCollection, - restoreArchivedDoc, - patchDoc, - getDocForArchiving, - markDocAsArchived, - getDocVersion, - checkRevUnchanged, - destroyProject, -} - -const methods = Object.getOwnPropertyNames(module.exports) -module.exports.promises = {} -for (const method of methods) { - metrics.timeAsyncMethod(module.exports, method, 'mongo.MongoManager', logger) - module.exports.promises[method] = promisify(module.exports[method]) + findDoc: callbackify(findDoc), + getProjectsDeletedDocs: callbackify(getProjectsDeletedDocs), + getProjectsDocs: callbackify(getProjectsDocs), + getArchivedProjectDocs: callbackify(getArchivedProjectDocs), + getNonArchivedProjectDocIds: callbackify(getNonArchivedProjectDocIds), + getNonDeletedArchivedProjectDocs: callbackify( + getNonDeletedArchivedProjectDocs + ), + upsertIntoDocCollection: callbackify(upsertIntoDocCollection), + restoreArchivedDoc: callbackify(restoreArchivedDoc), + patchDoc: callbackify(patchDoc), + getDocForArchiving: callbackify(getDocForArchiving), + markDocAsArchived: callbackify(markDocAsArchived), + getDocVersion: callbackify(getDocVersion), + checkRevUnchanged: callbackify(checkRevUnchanged), + destroyProject: callbackify(destroyProject), + promises: { + findDoc, + getProjectsDeletedDocs, + getProjectsDocs, + getArchivedProjectDocs, + getNonArchivedProjectDocIds, + getNonDeletedArchivedProjectDocs, + upsertIntoDocCollection, + restoreArchivedDoc, + patchDoc, + getDocForArchiving, + markDocAsArchived, + getDocVersion, + checkRevUnchanged, + destroyProject, + }, } diff --git a/services/docstore/test/unit/js/MongoManagerTests.js b/services/docstore/test/unit/js/MongoManagerTests.js index ed369bb02c..1dc3628307 100644 --- a/services/docstore/test/unit/js/MongoManagerTests.js +++ b/services/docstore/test/unit/js/MongoManagerTests.js @@ -12,8 +12,8 @@ describe('MongoManager', function () { beforeEach(function () { this.db = { docs: { - updateOne: sinon.stub().yields(null, { matchedCount: 1 }), - insertOne: sinon.stub().yields(null), + updateOne: sinon.stub().resolves({ matchedCount: 1 }), + insertOne: sinon.stub().resolves(), }, docOps: {}, } @@ -34,21 +34,19 @@ describe('MongoManager', function () { this.projectId = new ObjectId().toString() this.docId = new ObjectId().toString() this.rev = 42 - this.callback = sinon.stub() this.stubbedErr = new Error('hello world') this.lines = ['Three French hens', 'Two turtle doves'] }) describe('findDoc', function () { - beforeEach(function () { + beforeEach(async function () { this.doc = { name: 'mock-doc' } - this.db.docs.findOne = sinon.stub().callsArgWith(2, null, this.doc) + this.db.docs.findOne = sinon.stub().resolves(this.doc) this.filter = { lines: true } - this.MongoManager.findDoc( + this.result = await this.MongoManager.promises.findDoc( this.projectId, this.docId, - this.filter, - this.callback + this.filter ) }) @@ -66,20 +64,18 @@ describe('MongoManager', function () { .should.equal(true) }) - it('should call the callback with the doc', function () { - this.callback.calledWith(null, this.doc).should.equal(true) + it('should return the doc', function () { + expect(this.doc).to.deep.equal(this.doc) }) }) describe('patchDoc', function () { - beforeEach(function (done) { + beforeEach(async function () { this.meta = { name: 'foo.tex' } - this.callback.callsFake(done) - this.MongoManager.patchDoc( + await this.MongoManager.promises.patchDoc( this.projectId, this.docId, - this.meta, - this.callback + this.meta ) }) @@ -91,8 +87,7 @@ describe('MongoManager', function () { }, { $set: this.meta, - }, - this.callback + } ) }) }) @@ -105,19 +100,16 @@ describe('MongoManager', function () { this.doc3 = { name: 'mock-doc3' } this.doc4 = { name: 'mock-doc4' } this.db.docs.find = sinon.stub().returns({ - toArray: sinon - .stub() - .callsArgWith(0, null, [this.doc, this.doc3, this.doc4]), + toArray: sinon.stub().resolves([this.doc, this.doc3, this.doc4]), }) }) describe('with included_deleted = false', function () { - beforeEach(function () { - this.MongoManager.getProjectsDocs( + beforeEach(async function () { + this.result = await this.MongoManager.promises.getProjectsDocs( this.projectId, { include_deleted: false }, - this.filter, - this.callback + this.filter ) }) @@ -135,20 +127,17 @@ describe('MongoManager', function () { .should.equal(true) }) - it('should call the callback with the docs', function () { - this.callback - .calledWith(null, [this.doc, this.doc3, this.doc4]) - .should.equal(true) + it('should call return the docs', function () { + expect(this.result).to.deep.equal([this.doc, this.doc3, this.doc4]) }) }) describe('with included_deleted = true', function () { - beforeEach(function () { - this.MongoManager.getProjectsDocs( + beforeEach(async function () { + this.result = await this.MongoManager.promises.getProjectsDocs( this.projectId, { include_deleted: true }, - this.filter, - this.callback + this.filter ) }) @@ -165,28 +154,24 @@ describe('MongoManager', function () { .should.equal(true) }) - it('should call the callback with the docs', function () { - this.callback - .calledWith(null, [this.doc, this.doc3, this.doc4]) - .should.equal(true) + it('should return the docs', function () { + expect(this.result).to.deep.equal([this.doc, this.doc3, this.doc4]) }) }) }) describe('getProjectsDeletedDocs', function () { - beforeEach(function (done) { + beforeEach(async function () { this.filter = { name: true } this.doc1 = { _id: '1', name: 'mock-doc1.tex' } this.doc2 = { _id: '2', name: 'mock-doc2.tex' } this.doc3 = { _id: '3', name: 'mock-doc3.tex' } this.db.docs.find = sinon.stub().returns({ - toArray: sinon.stub().yields(null, [this.doc1, this.doc2, this.doc3]), + toArray: sinon.stub().resolves([this.doc1, this.doc2, this.doc3]), }) - this.callback.callsFake(done) - this.MongoManager.getProjectsDeletedDocs( + this.result = await this.MongoManager.promises.getProjectsDeletedDocs( this.projectId, - this.filter, - this.callback + this.filter ) }) @@ -209,10 +194,8 @@ describe('MongoManager', function () { .should.equal(true) }) - it('should call the callback with the docs', function () { - this.callback - .calledWith(null, [this.doc1, this.doc2, this.doc3]) - .should.equal(true) + it('should return the docs', function () { + expect(this.result).to.deep.equal([this.doc1, this.doc2, this.doc3]) }) }) @@ -221,108 +204,97 @@ describe('MongoManager', function () { this.oldRev = 77 }) - it('should upsert the document', function (done) { - this.MongoManager.upsertIntoDocCollection( + it('should upsert the document', async function () { + await this.MongoManager.promises.upsertIntoDocCollection( this.projectId, this.docId, this.oldRev, - { lines: this.lines }, - err => { - assert.equal(err, null) - const args = this.db.docs.updateOne.args[0] - assert.deepEqual(args[0], { - _id: new ObjectId(this.docId), - project_id: new ObjectId(this.projectId), - rev: this.oldRev, - }) - assert.equal(args[1].$set.lines, this.lines) - assert.equal(args[1].$inc.rev, 1) - done() - } + { lines: this.lines } ) + + const args = this.db.docs.updateOne.args[0] + assert.deepEqual(args[0], { + _id: new ObjectId(this.docId), + project_id: new ObjectId(this.projectId), + rev: this.oldRev, + }) + assert.equal(args[1].$set.lines, this.lines) + assert.equal(args[1].$inc.rev, 1) }) - it('should handle update error', function (done) { - this.db.docs.updateOne.yields(this.stubbedErr) - this.MongoManager.upsertIntoDocCollection( - this.projectId, - this.docId, - this.rev, - { lines: this.lines }, - err => { - err.should.equal(this.stubbedErr) - done() - } - ) - }) - - it('should insert without a previous rev', function (done) { - this.MongoManager.upsertIntoDocCollection( - this.projectId, - this.docId, - null, - { lines: this.lines, ranges: this.ranges }, - err => { - expect(this.db.docs.insertOne).to.have.been.calledWith({ - _id: new ObjectId(this.docId), - project_id: new ObjectId(this.projectId), - rev: 1, + it('should handle update error', async function () { + this.db.docs.updateOne.rejects(this.stubbedErr) + await expect( + this.MongoManager.promises.upsertIntoDocCollection( + this.projectId, + this.docId, + this.rev, + { lines: this.lines, - ranges: this.ranges, - }) - expect(err).to.not.exist - done() - } - ) + } + ) + ).to.be.rejectedWith(this.stubbedErr) }) - it('should handle generic insert error', function (done) { - this.db.docs.insertOne.yields(this.stubbedErr) - this.MongoManager.upsertIntoDocCollection( + it('should insert without a previous rev', async function () { + await this.MongoManager.promises.upsertIntoDocCollection( this.projectId, this.docId, null, - { lines: this.lines, ranges: this.ranges }, - err => { - expect(err).to.equal(this.stubbedErr) - done() - } + { lines: this.lines, ranges: this.ranges } ) + + expect(this.db.docs.insertOne).to.have.been.calledWith({ + _id: new ObjectId(this.docId), + project_id: new ObjectId(this.projectId), + rev: 1, + lines: this.lines, + ranges: this.ranges, + }) }) - it('should handle duplicate insert error', function (done) { - this.db.docs.insertOne.yields({ code: 11000 }) - this.MongoManager.upsertIntoDocCollection( - this.projectId, - this.docId, - null, - { lines: this.lines, ranges: this.ranges }, - err => { - expect(err).to.be.instanceof(Errors.DocRevValueError) - done() - } - ) + it('should handle generic insert error', async function () { + this.db.docs.insertOne.rejects(this.stubbedErr) + await expect( + this.MongoManager.promises.upsertIntoDocCollection( + this.projectId, + this.docId, + null, + { lines: this.lines, ranges: this.ranges } + ) + ).to.be.rejectedWith(this.stubbedErr) + }) + + it('should handle duplicate insert error', async function () { + this.db.docs.insertOne.rejects({ code: 11000 }) + await expect( + this.MongoManager.promises.upsertIntoDocCollection( + this.projectId, + this.docId, + null, + { lines: this.lines, ranges: this.ranges } + ) + ).to.be.rejectedWith(Errors.DocRevValueError) }) }) describe('destroyProject', function () { - beforeEach(function (done) { + beforeEach(async function () { this.projectId = new ObjectId() this.docIds = [new ObjectId(), new ObjectId()] - this.db.docs.deleteMany = sinon.stub().yields() - this.db.docOps.deleteMany = sinon.stub().yields() + this.db.docs.deleteMany = sinon.stub().resolves() + this.db.docOps.deleteMany = sinon.stub().resolves() this.db.docs.find = sinon .stub() .withArgs({ project_id: this.projectId }) .returns({ - toArray: sinon.stub().yields( - null, + toArray: sinon.stub().resolves( this.docIds.map(id => ({ _id: id, })) ), }) - this.MongoManager.destroyProject(this.projectId, done) + await this.MongoManager.promises.destroyProject(this.projectId) }) it('should destroy all docs', function () { @@ -340,10 +312,10 @@ describe('MongoManager', function () { describe('getDocVersion', function () { describe('when the doc exists', function () { - beforeEach(function () { + beforeEach(async function () { this.doc = { version: (this.version = 42) } - this.db.docOps.findOne = sinon.stub().callsArgWith(2, null, this.doc) - this.MongoManager.getDocVersion(this.docId, this.callback) + this.db.docOps.findOne = sinon.stub().resolves(this.doc) + this.result = await this.MongoManager.promises.getDocVersion(this.docId) }) it('should look for the doc in the database', function () { @@ -357,19 +329,19 @@ describe('MongoManager', function () { .should.equal(true) }) - it('should call the callback with the version', function () { - this.callback.calledWith(null, this.version).should.equal(true) + it('should return the version', function () { + expect(this.result).to.equal(this.version) }) }) describe("when the doc doesn't exist", function () { - beforeEach(function () { - this.db.docOps.findOne = sinon.stub().callsArgWith(2, null, null) - this.MongoManager.getDocVersion(this.docId, this.callback) + beforeEach(async function () { + this.db.docOps.findOne = sinon.stub().resolves(null) + this.result = await this.MongoManager.promises.getDocVersion(this.docId) }) - it('should call the callback with 0', function () { - this.callback.calledWith(null, 0).should.equal(true) + it('should return 0', function () { + expect(this.result).to.equal(0) }) }) }) @@ -379,37 +351,31 @@ describe('MongoManager', function () { this.doc = { _id: new ObjectId(), name: 'mock-doc', rev: 1 } }) - it('should call the callback when the rev has not changed', function (done) { - this.db.docs.findOne = sinon.stub().callsArgWith(2, null, { rev: 1 }) - this.MongoManager.checkRevUnchanged(this.doc, err => { - assert.isUndefined(err) - done() - }) + it('should not error when the rev has not changed', async function () { + this.db.docs.findOne = sinon.stub().resolves({ rev: 1 }) + await this.MongoManager.promises.checkRevUnchanged(this.doc) }) - it('should return an error when the rev has changed', function (done) { - this.db.docs.findOne = sinon.stub().callsArgWith(2, null, { rev: 2 }) - this.MongoManager.checkRevUnchanged(this.doc, err => { - err.should.be.instanceof(Errors.DocModifiedError) - done() - }) + it('should return an error when the rev has changed', async function () { + this.db.docs.findOne = sinon.stub().resolves({ rev: 2 }) + await expect( + this.MongoManager.promises.checkRevUnchanged(this.doc) + ).to.be.rejectedWith(Errors.DocModifiedError) }) - it('should return a value error if incoming rev is NaN', function (done) { - this.db.docs.findOne = sinon.stub().callsArgWith(2, null, { rev: 2 }) + it('should return a value error if incoming rev is NaN', async function () { + this.db.docs.findOne = sinon.stub().resolves({ rev: 2 }) this.doc = { _id: new ObjectId(), name: 'mock-doc', rev: NaN } - this.MongoManager.checkRevUnchanged(this.doc, err => { - err.should.be.instanceof(Errors.DocRevValueError) - done() - }) + await expect( + this.MongoManager.promises.checkRevUnchanged(this.doc) + ).to.be.rejectedWith(Errors.DocRevValueError) }) - it('should return a value error if checked doc rev is NaN', function (done) { - this.db.docs.findOne = sinon.stub().callsArgWith(2, null, { rev: NaN }) - this.MongoManager.checkRevUnchanged(this.doc, err => { - err.should.be.instanceof(Errors.DocRevValueError) - done() - }) + it('should return a value error if checked doc rev is NaN', async function () { + this.db.docs.findOne = sinon.stub().resolves({ rev: NaN }) + await expect( + this.MongoManager.promises.checkRevUnchanged(this.doc) + ).to.be.rejectedWith(Errors.DocRevValueError) }) }) @@ -423,12 +389,11 @@ describe('MongoManager', function () { }) describe('complete doc', function () { - beforeEach(function (done) { - this.MongoManager.restoreArchivedDoc( + beforeEach(async function () { + await this.MongoManager.promises.restoreArchivedDoc( this.projectId, this.docId, - this.archivedDoc, - done + this.archivedDoc ) }) @@ -453,13 +418,12 @@ describe('MongoManager', function () { }) describe('without ranges', function () { - beforeEach(function (done) { + beforeEach(async function () { delete this.archivedDoc.ranges - this.MongoManager.restoreArchivedDoc( + await this.MongoManager.promises.restoreArchivedDoc( this.projectId, this.docId, - this.archivedDoc, - done + this.archivedDoc ) }) @@ -484,17 +448,15 @@ describe('MongoManager', function () { }) describe("when the update doesn't succeed", function () { - it('throws a DocRevValueError', function (done) { - this.db.docs.updateOne.yields(null, { matchedCount: 0 }) - this.MongoManager.restoreArchivedDoc( - this.projectId, - this.docId, - this.archivedDoc, - err => { - expect(err).to.be.instanceof(Errors.DocRevValueError) - done() - } - ) + it('throws a DocRevValueError', async function () { + this.db.docs.updateOne.resolves({ matchedCount: 0 }) + await expect( + this.MongoManager.promises.restoreArchivedDoc( + this.projectId, + this.docId, + this.archivedDoc + ) + ).to.be.rejectedWith(Errors.DocRevValueError) }) }) })