Browse Source

Merge pull request #5984 from overleaf/em-unnecessarily-async-functions

Clean up unnecessarily async functions

GitOrigin-RevId: 59f0f0a76b4436f3b99a09b747670d443bac4582
Eric Mc Sween 4 years ago
parent
commit
b22df1dcba

+ 43 - 55
services/web/app/src/Features/Compile/ClsiManager.js

@@ -637,28 +637,22 @@ const ClsiManager = {
   },
 
   getContentFromDocUpdaterIfMatch(projectId, project, options, callback) {
-    ClsiStateManager.computeHash(project, options, (err, projectStateHash) => {
-      if (err != null) {
-        return callback(
-          OError.tag(err, 'Failed to compute project state hash', { projectId })
-        )
-      }
-      DocumentUpdaterHandler.getProjectDocsIfMatch(
-        projectId,
-        projectStateHash,
-        (err, docs) => {
-          if (err != null) {
-            return callback(
-              OError.tag(err, 'Failed to get project documents', {
-                projectId,
-                projectStateHash,
-              })
-            )
-          }
-          callback(null, projectStateHash, docs)
+    const projectStateHash = ClsiStateManager.computeHash(project, options)
+    DocumentUpdaterHandler.getProjectDocsIfMatch(
+      projectId,
+      projectStateHash,
+      (err, docs) => {
+        if (err != null) {
+          return callback(
+            OError.tag(err, 'Failed to get project documents', {
+              projectId,
+              projectStateHash,
+            })
+          )
         }
-      )
-    })
+        callback(null, projectStateHash, docs)
+      }
+    )
   },
 
   getOutputFileStream(projectId, userId, buildId, outputFilePath, callback) {
@@ -688,42 +682,36 @@ const ClsiManager = {
     docUpdaterDocs,
     callback
   ) {
-    ProjectEntityHandler.getAllDocPathsFromProject(project, (err, docPath) => {
-      if (err != null) {
-        return callback(
-          OError.tag(err, 'Failed to get doc paths', { projectId })
-        )
-      }
-      const docs = {}
-      for (const doc of docUpdaterDocs || []) {
-        const path = docPath[doc._id]
-        docs[path] = doc
-      }
-      // send new docs but not files as those are already on the clsi
-      options = _.clone(options)
-      options.syncType = 'incremental'
-      options.syncState = projectStateHash
-      // create stub doc entries for any possible root docs, if not
-      // present in the docupdater. This allows finaliseRequest to
-      // identify the root doc.
-      const possibleRootDocIds = [options.rootDoc_id, project.rootDoc_id]
-      for (const rootDocId of possibleRootDocIds) {
-        if (rootDocId != null && rootDocId in docPath) {
-          const path = docPath[rootDocId]
-          if (docs[path] == null) {
-            docs[path] = { _id: rootDocId, path }
-          }
+    const docPath = ProjectEntityHandler.getAllDocPathsFromProject(project)
+    const docs = {}
+    for (const doc of docUpdaterDocs || []) {
+      const path = docPath[doc._id]
+      docs[path] = doc
+    }
+    // send new docs but not files as those are already on the clsi
+    options = _.clone(options)
+    options.syncType = 'incremental'
+    options.syncState = projectStateHash
+    // create stub doc entries for any possible root docs, if not
+    // present in the docupdater. This allows finaliseRequest to
+    // identify the root doc.
+    const possibleRootDocIds = [options.rootDoc_id, project.rootDoc_id]
+    for (const rootDocId of possibleRootDocIds) {
+      if (rootDocId != null && rootDocId in docPath) {
+        const path = docPath[rootDocId]
+        if (docs[path] == null) {
+          docs[path] = { _id: rootDocId, path }
         }
       }
-      ClsiManager._finaliseRequest(
-        projectId,
-        options,
-        project,
-        docs,
-        [],
-        callback
-      )
-    })
+    }
+    ClsiManager._finaliseRequest(
+      projectId,
+      options,
+      project,
+      docs,
+      [],
+      callback
+    )
   },
 
   _buildRequestFromMongo(

+ 30 - 38
services/web/app/src/Features/Compile/ClsiStateManager.js

@@ -37,45 +37,37 @@ const buildState = s =>
   crypto.createHash('sha1').update(s, 'utf8').digest('hex')
 
 module.exports = ClsiStateManager = {
-  computeHash(project, options, callback) {
-    if (callback == null) {
-      callback = function () {}
-    }
-    return ProjectEntityHandler.getAllEntitiesFromProject(
-      project,
-      function (err, docs, files) {
-        const fileList = Array.from(files || []).map(
-          f => `${f.file._id}:${f.file.rev}:${f.file.created}:${f.path}`
-        )
-        const docList = Array.from(docs || []).map(
-          d => `${d.doc._id}:${d.path}`
-        )
-        const sortedEntityList = [
-          ...Array.from(docList),
-          ...Array.from(fileList),
-        ].sort()
-        // ignore the isAutoCompile options as it doesn't affect the
-        // output, but include all other options e.g. draft
-        const optionsList = (() => {
-          const result = []
-          const object = options || {}
-          for (const key in object) {
-            const value = object[key]
-            if (!['isAutoCompile'].includes(key)) {
-              result.push(`option ${key}:${value}`)
-            }
-          }
-          return result
-        })()
-        const sortedOptionsList = optionsList.sort()
-        const hash = buildState(
-          [
-            ...Array.from(sortedEntityList),
-            ...Array.from(sortedOptionsList),
-          ].join('\n')
-        )
-        return callback(null, hash)
+  computeHash(project, options) {
+    const { docs, files } = ProjectEntityHandler.getAllEntitiesFromProject(
+      project
+    )
+    const fileList = Array.from(files || []).map(
+      f => `${f.file._id}:${f.file.rev}:${f.file.created}:${f.path}`
+    )
+    const docList = Array.from(docs || []).map(d => `${d.doc._id}:${d.path}`)
+    const sortedEntityList = [
+      ...Array.from(docList),
+      ...Array.from(fileList),
+    ].sort()
+    // ignore the isAutoCompile options as it doesn't affect the
+    // output, but include all other options e.g. draft
+    const optionsList = (() => {
+      const result = []
+      const object = options || {}
+      for (const key in object) {
+        const value = object[key]
+        if (!['isAutoCompile'].includes(key)) {
+          result.push(`option ${key}:${value}`)
+        }
       }
+      return result
+    })()
+    const sortedOptionsList = optionsList.sort()
+    const hash = buildState(
+      [...Array.from(sortedEntityList), ...Array.from(sortedOptionsList)].join(
+        '\n'
+      )
     )
+    return hash
   },
 }

+ 11 - 16
services/web/app/src/Features/Project/ProjectController.js

@@ -356,23 +356,18 @@ const ProjectController = {
       if (err != null) {
         return next(err)
       }
-      ProjectEntityHandler.getAllEntitiesFromProject(
-        project,
-        (err, docs, files) => {
-          if (err != null) {
-            return next(err)
-          }
-          const entities = docs
-            .concat(files)
-            // Sort by path ascending
-            .sort((a, b) => (a.path > b.path ? 1 : a.path < b.path ? -1 : 0))
-            .map(e => ({
-              path: e.path,
-              type: e.doc != null ? 'doc' : 'file',
-            }))
-          res.json({ project_id: projectId, entities })
-        }
+      const { docs, files } = ProjectEntityHandler.getAllEntitiesFromProject(
+        project
       )
+      const entities = docs
+        .concat(files)
+        // Sort by path ascending
+        .sort((a, b) => (a.path > b.path ? 1 : a.path < b.path ? -1 : 0))
+        .map(e => ({
+          path: e.path,
+          type: e.doc != null ? 'doc' : 'file',
+        }))
+      res.json({ project_id: projectId, entities })
     })
   },
 

+ 31 - 36
services/web/app/src/Features/Project/ProjectEntityHandler.js

@@ -69,31 +69,28 @@ const ProjectEntityHandler = {
         return callback(new Errors.NotFoundError('project not found'))
       }
 
-      ProjectEntityHandler.getAllEntitiesFromProject(project, callback)
+      const entities = ProjectEntityHandler.getAllEntitiesFromProject(project)
+      callback(null, entities)
     })
   },
 
-  getAllEntitiesFromProject(project, callback) {
-    ProjectEntityHandler._getAllFoldersFromProject(project, (err, folders) => {
-      if (err != null) {
-        return callback(err)
-      }
-      const docs = []
-      const files = []
-      for (const { path: folderPath, folder } of folders) {
-        for (const doc of folder.docs || []) {
-          if (doc != null) {
-            docs.push({ path: path.join(folderPath, doc.name), doc })
-          }
+  getAllEntitiesFromProject(project) {
+    const folders = ProjectEntityHandler._getAllFoldersFromProject(project)
+    const docs = []
+    const files = []
+    for (const { path: folderPath, folder } of folders) {
+      for (const doc of folder.docs || []) {
+        if (doc != null) {
+          docs.push({ path: path.join(folderPath, doc.name), doc })
         }
-        for (const file of folder.fileRefs || []) {
-          if (file != null) {
-            files.push({ path: path.join(folderPath, file.name), file })
-          }
+      }
+      for (const file of folder.fileRefs || []) {
+        if (file != null) {
+          files.push({ path: path.join(folderPath, file.name), file })
         }
       }
-      callback(null, docs, files, folders)
-    })
+    }
+    return { docs, files, folders }
   },
 
   getAllDocPathsFromProjectById(projectId, callback) {
@@ -104,23 +101,20 @@ const ProjectEntityHandler = {
       if (project == null) {
         return callback(Errors.NotFoundError('no project'))
       }
-      ProjectEntityHandler.getAllDocPathsFromProject(project, callback)
+      const docPaths = ProjectEntityHandler.getAllDocPathsFromProject(project)
+      callback(null, docPaths)
     })
   },
 
-  getAllDocPathsFromProject(project, callback) {
-    ProjectEntityHandler._getAllFoldersFromProject(project, (err, folders) => {
-      if (err != null) {
-        return callback(err)
+  getAllDocPathsFromProject(project) {
+    const folders = ProjectEntityHandler._getAllFoldersFromProject(project)
+    const docPath = {}
+    for (const { path: folderPath, folder } of folders) {
+      for (const doc of folder.docs || []) {
+        docPath[doc._id] = path.join(folderPath, doc.name)
       }
-      const docPath = {}
-      for (const { path: folderPath, folder } of folders) {
-        for (const doc of folder.docs || []) {
-          docPath[doc._id] = path.join(folderPath, doc.name)
-        }
-      }
-      callback(null, docPath)
-    })
+    }
+    return docPath
   },
 
   getDoc(projectId, docId, options, callback) {
@@ -205,11 +199,12 @@ const ProjectEntityHandler = {
       if (project == null) {
         return callback(new Errors.NotFoundError('no project'))
       }
-      ProjectEntityHandler._getAllFoldersFromProject(project, callback)
+      const folders = ProjectEntityHandler._getAllFoldersFromProject(project)
+      callback(null, folders)
     })
   },
 
-  _getAllFoldersFromProject(project, callback) {
+  _getAllFoldersFromProject(project) {
     const folders = []
     function processFolder(basePath, folder) {
       folders.push({ path: basePath, folder })
@@ -221,15 +216,15 @@ const ProjectEntityHandler = {
     }
 
     processFolder('/', project.rootFolder[0])
-    callback(null, folders)
+    return folders
   },
 }
 
 module.exports = ProjectEntityHandler
 module.exports.promises = promisifyAll(ProjectEntityHandler, {
+  without: ['getAllEntitiesFromProject'],
   multiResult: {
     getAllEntities: ['docs', 'files'],
-    getAllEntitiesFromProject: ['docs', 'files'],
     getDoc: ['lines', 'rev', 'version', 'ranges'],
   },
 })

+ 4 - 4
services/web/app/src/Features/Project/ProjectEntityMongoUpdateHandler.js

@@ -301,7 +301,7 @@ async function moveEntity(projectId, entityId, destFolderId, entityType) {
   const {
     docs: oldDocs,
     files: oldFiles,
-  } = await ProjectEntityHandler.promises.getAllEntitiesFromProject(project)
+  } = ProjectEntityHandler.getAllEntitiesFromProject(project)
   // For safety, insert the entity in the destination
   // location first, and then remove the original.  If
   // there is an error the entity may appear twice. This
@@ -331,7 +331,7 @@ async function moveEntity(projectId, entityId, destFolderId, entityType) {
   const {
     docs: newDocs,
     files: newFiles,
-  } = await ProjectEntityHandler.promises.getAllEntitiesFromProject(newProject)
+  } = ProjectEntityHandler.getAllEntitiesFromProject(newProject)
   const startPath = entityPath.fileSystem
   const endPath = result.path.fileSystem
   const changes = {
@@ -421,7 +421,7 @@ async function renameEntity(
   const {
     docs: oldDocs,
     files: oldFiles,
-  } = await ProjectEntityHandler.promises.getAllEntitiesFromProject(project)
+  } = ProjectEntityHandler.getAllEntitiesFromProject(project)
 
   // we need to increment the project version number for any structure change
   const newProject = await Project.findOneAndUpdate(
@@ -433,7 +433,7 @@ async function renameEntity(
   const {
     docs: newDocs,
     files: newFiles,
-  } = await ProjectEntityHandler.promises.getAllEntitiesFromProject(newProject)
+  } = ProjectEntityHandler.getAllEntitiesFromProject(newProject)
   return {
     project,
     startPath,

+ 29 - 32
services/web/app/src/Features/Project/ProjectEntityUpdateHandler.js

@@ -1349,42 +1349,39 @@ const ProjectEntityUpdateHandler = {
           return callback(error)
         }
 
-        ProjectEntityHandler.getAllEntitiesFromProject(
-          project,
-          (error, docs, files, folders) => {
-            if (error != null) {
+        let {
+          docs,
+          files,
+          folders,
+        } = ProjectEntityHandler.getAllEntitiesFromProject(project)
+        // _checkFileTree() must be passed the folders before docs and
+        // files
+        ProjectEntityUpdateHandler._checkFiletree(
+          projectId,
+          projectHistoryId,
+          [...folders, ...docs, ...files],
+          error => {
+            if (error) {
               return callback(error)
             }
-            // _checkFileTree() must be passed the folders before docs and
-            // files
-            ProjectEntityUpdateHandler._checkFiletree(
-              projectId,
-              projectHistoryId,
-              [...folders, ...docs, ...files],
-              error => {
-                if (error) {
-                  return callback(error)
-                }
-                docs = _.map(docs, doc => ({
-                  doc: doc.doc._id,
-                  path: doc.path,
-                }))
+            docs = _.map(docs, doc => ({
+              doc: doc.doc._id,
+              path: doc.path,
+            }))
 
-                files = _.map(files, file => ({
-                  file: file.file._id,
-                  path: file.path,
-                  url: FileStoreHandler._buildUrl(projectId, file.file._id),
-                  _hash: file.file.hash,
-                }))
+            files = _.map(files, file => ({
+              file: file.file._id,
+              path: file.path,
+              url: FileStoreHandler._buildUrl(projectId, file.file._id),
+              _hash: file.file.hash,
+            }))
 
-                DocumentUpdaterHandler.resyncProjectHistory(
-                  projectId,
-                  projectHistoryId,
-                  docs,
-                  files,
-                  callback
-                )
-              }
+            DocumentUpdaterHandler.resyncProjectHistory(
+              projectId,
+              projectHistoryId,
+              docs,
+              files,
+              callback
             )
           }
         )

+ 3 - 4
services/web/scripts/count_files_in_projects.js

@@ -17,10 +17,9 @@ async function countFiles() {
       if (!project) {
         throw new Errors.NotFoundError('project not found')
       }
-      const {
-        files,
-        docs,
-      } = await ProjectEntityHandler.promises.getAllEntitiesFromProject(project)
+      const { files, docs } = ProjectEntityHandler.getAllEntitiesFromProject(
+        project
+      )
       console.error(
         projectId,
         files.length,

+ 7 - 13
services/web/test/unit/src/Compile/ClsiManagerTests.js

@@ -13,7 +13,7 @@ describe('ClsiManager', function () {
       _getServerId: sinon.stub(),
     }
     this.ClsiStateManager = {
-      computeHash: sinon.stub().callsArgWith(2, null, '01234567890abcdef'),
+      computeHash: sinon.stub().returns('01234567890abcdef'),
     }
     this.ClsiFormatChecker = {
       checkRecoursesForProblems: sinon.stub().callsArgWith(1),
@@ -645,13 +645,10 @@ describe('ClsiManager', function () {
 
     describe('with the incremental compile option', function () {
       beforeEach(function (done) {
+        this.project_state_hash = '01234567890abcdef'
         this.ClsiStateManager.computeHash = sinon
           .stub()
-          .callsArgWith(
-            2,
-            null,
-            (this.project_state_hash = '01234567890abcdef')
-          )
+          .returns(this.project_state_hash)
         this.DocumentUpdaterHandler.getProjectDocsIfMatch = sinon
           .stub()
           .callsArgWith(2, null, [
@@ -659,7 +656,7 @@ describe('ClsiManager', function () {
           ])
         this.ProjectEntityHandler.getAllDocPathsFromProject = sinon
           .stub()
-          .callsArgWith(1, null, { 'mock-doc-id-1': 'main.tex' })
+          .returns({ 'mock-doc-id-1': 'main.tex' })
         this.ClsiManager._buildRequest(
           this.project_id,
           {
@@ -732,13 +729,10 @@ describe('ClsiManager', function () {
 
       describe('when the root doc is set and not in the docupdater', function () {
         beforeEach(function (done) {
+          this.project_state_hash = '01234567890abcdef'
           this.ClsiStateManager.computeHash = sinon
             .stub()
-            .callsArgWith(
-              2,
-              null,
-              (this.project_state_hash = '01234567890abcdef')
-            )
+            .returns(this.project_state_hash)
           this.DocumentUpdaterHandler.getProjectDocsIfMatch = sinon
             .stub()
             .callsArgWith(2, null, [
@@ -746,7 +740,7 @@ describe('ClsiManager', function () {
             ])
           this.ProjectEntityHandler.getAllDocPathsFromProject = sinon
             .stub()
-            .callsArgWith(1, null, {
+            .returns({
               'mock-doc-id-1': 'main.tex',
               'mock-doc-id-2': '/chapters/chapter1.tex',
             })

+ 61 - 152
services/web/test/unit/src/Compile/ClsiStateManagerTests.js

@@ -31,7 +31,7 @@ describe('ClsiStateManager', function () {
   })
 
   describe('computeHash', function () {
-    beforeEach(function (done) {
+    beforeEach(function () {
       this.docs = [
         { path: '/main.tex', doc: { _id: 'doc-id-1' } },
         { path: '/folder/sub.tex', doc: { _id: 'doc-id-2' } },
@@ -48,30 +48,17 @@ describe('ClsiStateManager', function () {
       ]
       this.ProjectEntityHandler.getAllEntitiesFromProject = sinon
         .stub()
-        .callsArgWith(1, null, this.docs, this.files)
-      return this.ClsiStateManager.computeHash(
-        this.project,
-        this.options,
-        (err, hash) => {
-          this.hash0 = hash
-          return done()
-        }
-      )
+        .returns({ docs: this.docs, files: this.files })
+      this.hash0 = this.ClsiStateManager.computeHash(this.project, this.options)
     })
 
     describe('with a sample project', function () {
-      beforeEach(function () {
-        return this.ClsiStateManager.computeHash(
-          this.project,
-          this.options,
-          this.callback
-        )
-      })
+      beforeEach(function () {})
 
-      it('should call the callback with a hash value', function () {
-        return this.callback
-          .calledWith(null, '21b1ab73aa3892bec452baf8ffa0956179e1880f')
-          .should.equal(true)
+      it('should return a hash value', function () {
+        expect(
+          this.ClsiStateManager.computeHash(this.project, this.options)
+        ).to.equal('21b1ab73aa3892bec452baf8ffa0956179e1880f')
       })
     })
 
@@ -82,213 +69,135 @@ describe('ClsiStateManager', function () {
           this.files[1],
           this.files[0],
         ])
-        return this.ClsiStateManager.computeHash(
-          this.project,
-          this.options,
-          this.callback
-        )
       })
 
-      it('should call the callback with the same hash value', function () {
-        return this.callback.calledWith(null, this.hash0).should.equal(true)
+      it('should return the same hash value', function () {
+        expect(
+          this.ClsiStateManager.computeHash(this.project, this.options)
+        ).to.equal(this.hash0)
       })
     })
 
     describe('when a doc is renamed', function () {
-      beforeEach(function (done) {
+      beforeEach(function () {
         this.docs[0].path = '/new.tex'
-        return this.ClsiStateManager.computeHash(
-          this.project,
-          this.options,
-          (err, hash) => {
-            this.hash1 = hash
-            return done()
-          }
-        )
       })
 
-      it('should call the callback with a different hash value', function () {
-        return this.callback
-          .neverCalledWith(null, this.hash0)
-          .should.equal(true)
+      it('should return a different hash value', function () {
+        expect(
+          this.ClsiStateManager.computeHash(this.project, this.options)
+        ).not.to.equal(this.hash0)
       })
     })
 
     describe('when a file is renamed', function () {
-      beforeEach(function (done) {
+      beforeEach(function () {
         this.files[0].path = '/newfigure.pdf'
-        return this.ClsiStateManager.computeHash(
-          this.project,
-          this.options,
-          (err, hash) => {
-            this.hash1 = hash
-            return done()
-          }
-        )
       })
 
-      it('should call the callback with a different hash value', function () {
-        return this.callback
-          .neverCalledWith(null, this.hash0)
-          .should.equal(true)
+      it('should return a different hash value', function () {
+        expect(
+          this.ClsiStateManager.computeHash(this.project, this.options)
+        ).not.to.equal(this.hash0)
       })
     })
 
     describe('when a doc is added', function () {
-      beforeEach(function (done) {
+      beforeEach(function () {
         this.docs.push({ path: '/newdoc.tex', doc: { _id: 'newdoc-id' } })
-        return this.ClsiStateManager.computeHash(
-          this.project,
-          this.options,
-          (err, hash) => {
-            this.hash1 = hash
-            return done()
-          }
-        )
       })
 
-      it('should call the callback with a different hash value', function () {
-        return this.callback
-          .neverCalledWith(null, this.hash0)
-          .should.equal(true)
+      it('should return a different hash value', function () {
+        expect(
+          this.ClsiStateManager.computeHash(this.project, this.options)
+        ).not.to.equal(this.hash0)
       })
     })
 
     describe('when a file is added', function () {
-      beforeEach(function (done) {
+      beforeEach(function () {
         this.files.push({
           path: '/newfile.tex',
           file: { _id: 'newfile-id', rev: 123 },
         })
-        return this.ClsiStateManager.computeHash(
-          this.project,
-          this.options,
-          (err, hash) => {
-            this.hash1 = hash
-            return done()
-          }
-        )
       })
 
-      it('should call the callback with a different hash value', function () {
-        return this.callback
-          .neverCalledWith(null, this.hash0)
-          .should.equal(true)
+      it('should return a different hash value', function () {
+        expect(
+          this.ClsiStateManager.computeHash(this.project, this.options)
+        ).not.to.equal(this.hash0)
       })
     })
 
     describe('when a doc is removed', function () {
-      beforeEach(function (done) {
+      beforeEach(function () {
         this.docs.pop()
-        return this.ClsiStateManager.computeHash(
-          this.project,
-          this.options,
-          (err, hash) => {
-            this.hash1 = hash
-            return done()
-          }
-        )
       })
 
-      it('should call the callback with a different hash value', function () {
-        return this.callback
-          .neverCalledWith(null, this.hash0)
-          .should.equal(true)
+      it('should return a different hash value', function () {
+        expect(
+          this.ClsiStateManager.computeHash(this.project, this.options)
+        ).not.to.equal(this.hash0)
       })
     })
 
     describe('when a file is removed', function () {
-      beforeEach(function (done) {
+      beforeEach(function () {
         this.files.pop()
-        return this.ClsiStateManager.computeHash(
-          this.project,
-          this.options,
-          (err, hash) => {
-            this.hash1 = hash
-            return done()
-          }
-        )
       })
 
-      it('should call the callback with a different hash value', function () {
-        return this.callback
-          .neverCalledWith(null, this.hash0)
-          .should.equal(true)
+      it('should return a different hash value', function () {
+        expect(
+          this.ClsiStateManager.computeHash(this.project, this.options)
+        ).not.to.equal(this.hash0)
       })
     })
 
     describe("when a file's revision is updated", function () {
-      beforeEach(function (done) {
+      beforeEach(function () {
         this.files[0].file.rev++
-        return this.ClsiStateManager.computeHash(
-          this.project,
-          this.options,
-          (err, hash) => {
-            this.hash1 = hash
-            return done()
-          }
-        )
       })
 
-      it('should call the callback with a different hash value', function () {
-        return this.callback
-          .neverCalledWith(null, this.hash0)
-          .should.equal(true)
+      it('should return a different hash value', function () {
+        expect(
+          this.ClsiStateManager.computeHash(this.project, this.options)
+        ).not.to.equal(this.hash0)
       })
     })
 
     describe("when a file's date is updated", function () {
-      beforeEach(function (done) {
+      beforeEach(function () {
         this.files[0].file.created = 'zzzzzz'
-        return this.ClsiStateManager.computeHash(
-          this.project,
-          this.options,
-          (err, hash) => {
-            this.hash1 = hash
-            return done()
-          }
-        )
       })
 
-      it('should call the callback with a different hash value', function () {
-        return this.callback
-          .neverCalledWith(null, this.hash0)
-          .should.equal(true)
+      it('should return a different hash value', function () {
+        expect(
+          this.ClsiStateManager.computeHash(this.project, this.options)
+        ).not.to.equal(this.hash0)
       })
     })
 
     describe('when the compile options are changed', function () {
-      beforeEach(function (done) {
+      beforeEach(function () {
         this.options.draft = !this.options.draft
-        return this.ClsiStateManager.computeHash(
-          this.project,
-          this.options,
-          (err, hash) => {
-            this.hash1 = hash
-            return done()
-          }
-        )
       })
 
-      it('should call the callback with a different hash value', function () {
-        return this.callback
-          .neverCalledWith(null, this.hash0)
-          .should.equal(true)
+      it('should return a different hash value', function () {
+        expect(
+          this.ClsiStateManager.computeHash(this.project, this.options)
+        ).not.to.equal(this.hash0)
       })
     })
 
     describe('when the isAutoCompile option is changed', function () {
       beforeEach(function () {
         this.options.isAutoCompile = !this.options.isAutoCompile
-        return this.ClsiStateManager.computeHash(
-          this.project,
-          this.options,
-          this.callback
-        )
       })
 
-      it('should call the callback with the same hash value', function () {
-        return this.callback.calledWith(null, this.hash0).should.equal(true)
+      it('should return the same hash value', function () {
+        expect(
+          this.ClsiStateManager.computeHash(this.project, this.options)
+        ).to.equal(this.hash0)
       })
     })
   })

+ 1 - 1
services/web/test/unit/src/Project/ProjectControllerTests.js

@@ -1743,7 +1743,7 @@ describe('ProjectController', function () {
         .callsArgWith(1, null, this.project)
       this.ProjectEntityHandler.getAllEntitiesFromProject = sinon
         .stub()
-        .callsArgWith(1, null, this.docs, this.files)
+        .returns({ docs: this.docs, files: this.files })
     })
 
     it('should produce a list of entities', function (done) {

+ 17 - 16
services/web/test/unit/src/Project/ProjectEntityHandlerTests.js

@@ -161,18 +161,19 @@ describe('ProjectEntityHandler', function () {
             rev: (this.rev2 = 2),
           },
         ]
-        this.callback = sinon.stub()
-        this.ProjectEntityHandler.getAllDocPathsFromProject(
-          this.project,
-          this.callback
-        )
       })
 
       it('should call the callback with the path for each docId', function () {
-        this.expected = {}
-        this.expected[this.doc1._id] = `/${this.doc1.name}`
-        this.expected[this.doc2._id] = `/folder1/${this.doc2.name}`
-        this.callback.calledWith(null, this.expected).should.equal(true)
+        const expected = {
+          [this.doc1._id]: `/${this.doc1.name}`,
+          [this.doc2._id]: `/folder1/${this.doc2.name}`,
+        }
+        expect(
+          this.ProjectEntityHandler.getAllDocPathsFromProject(
+            this.project,
+            this.callback
+          )
+        ).to.deep.equal(expected)
       })
     })
 
@@ -254,13 +255,13 @@ describe('ProjectEntityHandler', function () {
         )
       })
 
-      it('should call the callback with the folders', function () {
-        this.callback
-          .calledWith(null, [
-            { path: '/', folder: this.project.rootFolder[0] },
-            { path: '/folder1', folder: this.folder1 },
-          ])
-          .should.equal(true)
+      it('should return the folders', function () {
+        expect(
+          this.ProjectEntityHandler._getAllFoldersFromProject(this.project)
+        ).to.deep.equal([
+          { path: '/', folder: this.project.rootFolder[0] },
+          { path: '/folder1', folder: this.folder1 },
+        ])
       })
     })
   })

+ 9 - 11
services/web/test/unit/src/Project/ProjectEntityMongoUpdateHandlerTests.js

@@ -74,9 +74,7 @@ describe('ProjectEntityMongoUpdateHandler', function () {
     this.DeletedFileMock = sinon.mock(DeletedFile)
     this.ProjectMock = sinon.mock(Project)
     this.ProjectEntityHandler = {
-      promises: {
-        getAllEntitiesFromProject: sinon.stub(),
-      },
+      getAllEntitiesFromProject: sinon.stub(),
     }
     this.ProjectLocator = {
       promises: {
@@ -635,12 +633,12 @@ describe('ProjectEntityMongoUpdateHandler', function () {
         this.newDocs = ['new-doc']
         this.newFiles = ['new-file']
 
-        this.ProjectEntityHandler.promises.getAllEntitiesFromProject
+        this.ProjectEntityHandler.getAllEntitiesFromProject
           .onFirstCall()
-          .resolves({ docs: this.oldDocs, files: this.oldFiles })
-        this.ProjectEntityHandler.promises.getAllEntitiesFromProject
+          .returns({ docs: this.oldDocs, files: this.oldFiles })
+        this.ProjectEntityHandler.getAllEntitiesFromProject
           .onSecondCall()
-          .resolves({ docs: this.newDocs, files: this.newFiles })
+          .returns({ docs: this.newDocs, files: this.newFiles })
 
         this.ProjectMock.expects('findOneAndUpdate')
           .withArgs(
@@ -751,12 +749,12 @@ describe('ProjectEntityMongoUpdateHandler', function () {
         this.newDocs = ['new-doc']
         this.newFiles = ['new-file']
 
-        this.ProjectEntityHandler.promises.getAllEntitiesFromProject
+        this.ProjectEntityHandler.getAllEntitiesFromProject
           .onFirstCall()
-          .resolves({ docs: this.oldDocs, files: this.oldFiles })
-        this.ProjectEntityHandler.promises.getAllEntitiesFromProject
+          .returns({ docs: this.oldDocs, files: this.oldFiles })
+        this.ProjectEntityHandler.getAllEntitiesFromProject
           .onSecondCall()
-          .resolves({ docs: this.newDocs, files: this.newFiles })
+          .returns({ docs: this.newDocs, files: this.newFiles })
 
         this.ProjectMock.expects('findOneAndUpdate')
           .withArgs(

+ 20 - 24
services/web/test/unit/src/Project/ProjectEntityUpdateHandlerTests.js

@@ -1932,12 +1932,12 @@ describe('ProjectEntityUpdateHandler', function () {
             path: 'universe.png',
           },
         ]
-        this.ProjectEntityHandler.getAllEntitiesFromProject.yields(
-          null,
+        const folders = []
+        this.ProjectEntityHandler.getAllEntitiesFromProject.returns({
           docs,
           files,
-          []
-        )
+          folders,
+        })
         this.ProjectEntityUpdateHandler.resyncProjectHistory(
           projectId,
           this.callback
@@ -2019,12 +2019,11 @@ describe('ProjectEntityUpdateHandler', function () {
             path: 'another dupe (22)',
           },
         ]
-        this.ProjectEntityHandler.getAllEntitiesFromProject.yields(
-          null,
-          this.docs,
-          this.files,
-          []
-        )
+        this.ProjectEntityHandler.getAllEntitiesFromProject.returns({
+          docs: this.docs,
+          files: this.files,
+          folders: [],
+        })
         this.ProjectEntityUpdateHandler.resyncProjectHistory(projectId, done)
       })
 
@@ -2121,12 +2120,11 @@ describe('ProjectEntityUpdateHandler', function () {
             path: 'A_.png',
           },
         ]
-        this.ProjectEntityHandler.getAllEntitiesFromProject.yields(
-          null,
-          this.docs,
-          this.files,
-          []
-        )
+        this.ProjectEntityHandler.getAllEntitiesFromProject.returns({
+          docs: this.docs,
+          files: this.files,
+          folders: [],
+        })
         this.ProjectEntityUpdateHandler.resyncProjectHistory(projectId, done)
       })
 
@@ -2209,12 +2207,11 @@ describe('ProjectEntityUpdateHandler', function () {
           },
         ]
         const files = []
-        this.ProjectEntityHandler.getAllEntitiesFromProject.yields(
-          null,
+        this.ProjectEntityHandler.getAllEntitiesFromProject.returns({
           docs,
           files,
-          folders
-        )
+          folders,
+        })
         this.ProjectEntityUpdateHandler.resyncProjectHistory(projectId, done)
       })
 
@@ -2261,12 +2258,11 @@ describe('ProjectEntityUpdateHandler', function () {
           },
         ]
         const files = []
-        this.ProjectEntityHandler.getAllEntitiesFromProject.yields(
-          null,
+        this.ProjectEntityHandler.getAllEntitiesFromProject.returns({
           docs,
           files,
-          folders
-        )
+          folders,
+        })
         this.ProjectEntityUpdateHandler.resyncProjectHistory(projectId, done)
       })