Просмотр исходного кода

Merge pull request #2356 from overleaf/em-upgrade-test-deps

Upgrade test dependencies

GitOrigin-RevId: 0bda49dea086f525211836b6008f67bafa2bbe48
Eric Mc Sween 6 лет назад
Родитель
Сommit
4f9eb281b7
37 измененных файлов с 882 добавлено и 652 удалено
  1. 270 264
      services/web/package-lock.json
  2. 5 6
      services/web/package.json
  3. 0 15
      services/web/test/acceptance/src/DeletionTests.js
  4. 7 4
      services/web/test/acceptance/src/ProjectStructureMongoLockTest.js
  5. 1 1
      services/web/test/acceptance/src/helpers/DeletedSubscription.js
  6. 5 3
      services/web/test/unit/bootstrap.js
  7. 4 2
      services/web/test/unit/src/Authorization/AuthorizationMiddlewareTests.js
  8. 6 6
      services/web/test/unit/src/Chat/ChatApiHandlerTests.js
  9. 25 19
      services/web/test/unit/src/Collaborators/CollaboratorsInviteControllerTests.js
  10. 37 15
      services/web/test/unit/src/Contact/ContactManagerTests.js
  11. 131 31
      services/web/test/unit/src/Docstore/DocstoreManagerTests.js
  12. 115 35
      services/web/test/unit/src/DocumentUpdater/DocumentUpdaterHandlerTests.js
  13. 4 3
      services/web/test/unit/src/Documents/DocumentControllerTests.js
  14. 6 11
      services/web/test/unit/src/Editor/EditorControllerTests.js
  15. 1 1
      services/web/test/unit/src/Email/EmailSenderTests.js
  16. 3 3
      services/web/test/unit/src/Errors/HttpErrorControllerTests.js
  17. 8 8
      services/web/test/unit/src/Project/ProjectCollabratecDetailsTest.js
  18. 2 2
      services/web/test/unit/src/Project/ProjectControllerTests.js
  19. 7 6
      services/web/test/unit/src/Project/ProjectDetailsHandlerTests.js
  20. 43 47
      services/web/test/unit/src/Project/ProjectEntityMongoUpdateHandlerTests.js
  21. 24 12
      services/web/test/unit/src/Project/ProjectEntityUpdateHandlerTests.js
  22. 1 1
      services/web/test/unit/src/Project/ProjectHistoryHandlerTests.js
  23. 3 3
      services/web/test/unit/src/Project/ProjectLocatorTests.js
  24. 10 2
      services/web/test/unit/src/Project/ProjectRootDocManagerTests.js
  25. 2 6
      services/web/test/unit/src/Project/ProjectUpdateHandlerTests.js
  26. 5 1
      services/web/test/unit/src/Security/SessionStoreManagerTests.js
  27. 49 42
      services/web/test/unit/src/Subscription/LimitationsManagerTests.js
  28. 39 57
      services/web/test/unit/src/Subscription/RecurlyWrapperTests.js
  29. 18 6
      services/web/test/unit/src/Tags/TagsHandlerTests.js
  30. 13 10
      services/web/test/unit/src/TokenAccess/TokenAccessControllerTests.js
  31. 28 23
      services/web/test/unit/src/Uploads/ArchiveManagerTests.js
  32. 1 1
      services/web/test/unit/src/Uploads/ProjectUploadManagerTests.js
  33. 1 1
      services/web/test/unit/src/User/UserDeleterTests.js
  34. 2 1
      services/web/test/unit/src/User/UserRegistrationHandlerTests.js
  35. 2 2
      services/web/test/unit/src/UserMembership/UserMembershipControllerTests.js
  36. 3 1
      services/web/test/unit/src/infrastructure/LockManager/getLockTests.js
  37. 1 1
      services/web/test/unit/src/infrastructure/ProxyManagerTests.js

Разница между файлами не показана из-за своего большого размера
+ 270 - 264
services/web/package-lock.json


+ 5 - 6
services/web/package.json

@@ -14,7 +14,7 @@
   "scripts": {
     "test:acceptance:run_dir": "mocha --recursive --reporter spec --timeout 25000 --exit --grep=$MOCHA_GREP --require test/acceptance/bootstrap.js",
     "test:acceptance:app": "npm run test:acceptance:run_dir -- test/acceptance/src",
-    "test:unit:run_dir": "mocha --recursive --reporter spec --timeout 25000 --exit --grep=$MOCHA_GREP --require test/unit/bootstrap.js",
+    "test:unit:run_dir": "mocha --recursive --reporter spec --timeout 25000 --exit --grep=$MOCHA_GREP --file test/unit/bootstrap.js",
     "test:unit:app": "npm run test:unit:run_dir -- test/unit/src",
     "test:frontend": "karma start",
     "test:frontend:single": "karma start --single-run",
@@ -77,7 +77,7 @@
     "metrics-sharelatex": "^2.2.0",
     "minimist": "1.2.0",
     "mmmagic": "^0.5.2",
-    "mocha": "^5.0.1",
+    "mocha": "^6.2.2",
     "mongojs": "2.4.0",
     "mongoose": "4.11.4",
     "multer": "git+https://github.com/overleaf/multer.git",
@@ -125,7 +125,7 @@
     "babel-eslint": "^10.0.2",
     "babel-loader": "^8.0.6",
     "babel-plugin-angularjs-annotate": "^0.10.0",
-    "chai": "3.5.0",
+    "chai": "^4.2.0",
     "chai-as-promised": "^7.1.1",
     "chaid": "^1.0.2",
     "cheerio": "^1.0.0-rc.3",
@@ -165,9 +165,8 @@
     "react-testing-library": "^5.4.2",
     "requirejs": "^2.1.22",
     "sandboxed-module": "0.2.0",
-    "sinon": "^1.17.0",
-    "sinon-as-promised": "^4.0.3",
-    "sinon-chai": "^2.14.0",
+    "sinon": "^7.5.0",
+    "sinon-chai": "^3.3.0",
     "sinon-mongoose": "^2.3.0",
     "timekeeper": "^2.2.0",
     "translations-sharelatex": "git+https://github.com/sharelatex/translations-sharelatex.git#master",

+ 0 - 15
services/web/test/acceptance/src/DeletionTests.js

@@ -255,21 +255,6 @@ describe('Deleting a project', function() {
       })
     })
 
-    it('should mark the docs as deleted', function(done) {
-      let doc =
-        MockDocstoreApi.docs[this.projectId.toString()][this.docId.toString()]
-      expect(doc).to.exist
-      expect(doc.deleted).to.be.falsey
-      this.user.deleteProject(this.projectId, error => {
-        expect(error).not.to.exist
-        let doc =
-          MockDocstoreApi.docs[this.projectId.toString()][this.docId.toString()]
-        expect(doc).to.exist
-        expect(doc.deleted).to.be.truthy
-        done()
-      })
-    })
-
     describe('When the deleted project is expired', function() {
       beforeEach(function(done) {
         this.user.deleteProject(this.projectId, error => {

+ 7 - 4
services/web/test/acceptance/src/ProjectStructureMongoLockTest.js

@@ -86,7 +86,8 @@ describe('ProjectStructureMongoLock', function() {
           const method = ProjectEntityMongoUpdateHandler[methodName]
           const args = _.times(method.length - 2, _.constant(null))
           return method(this.locked_project._id, args, err => {
-            expect(err).to.deep.equal(new Error('Timeout'))
+            expect(err).to.be.instanceOf(Error)
+            expect(err).to.have.property('message', 'Timeout')
             return done()
           })
         })
@@ -94,7 +95,8 @@ describe('ProjectStructureMongoLock', function() {
 
       it('cannot get the project without a projection', function(done) {
         return ProjectGetter.getProject(this.locked_project._id, err => {
-          expect(err).to.deep.equal(new Error('Timeout'))
+          expect(err).to.be.instanceOf(Error)
+          expect(err).to.have.property('message', 'Timeout')
           return done()
         })
       })
@@ -104,7 +106,8 @@ describe('ProjectStructureMongoLock', function() {
           this.locked_project._id,
           { rootFolder: true },
           err => {
-            expect(err).to.deep.equal(new Error('Timeout'))
+            expect(err).to.be.instanceOf(Error)
+            expect(err).to.have.property('message', 'Timeout')
             return done()
           }
         )
@@ -145,7 +148,7 @@ describe('ProjectStructureMongoLock', function() {
           'new folder',
           (err, folder) => {
             expect(err).to.equal(null)
-            expect(folder).to.be.defined
+            expect(folder).to.exist
             return done()
           }
         )

+ 1 - 1
services/web/test/acceptance/src/helpers/DeletedSubscription.js

@@ -31,7 +31,7 @@ class DeletedSubscription {
         SubscriptionModel.findById(
           this.subscription._id,
           (error, subscription) => {
-            expect(subscription).to.exists
+            expect(subscription).to.exist
             expect(subscription._id.toString()).to.equal(
               this.subscription._id.toString()
             )

+ 5 - 3
services/web/test/unit/bootstrap.js

@@ -1,5 +1,5 @@
 const chai = require('chai')
-require('sinon')
+const sinon = require('sinon')
 
 // Load sinon-chai assertions so expect(stubFn).to.have.been.calledWith('abc')
 // has a nicer failure messages
@@ -11,8 +11,6 @@ chai.use(require('chai-as-promised'))
 // Do not truncate assertion errors
 chai.config.truncateThreshold = 0
 
-// add support for promises in sinon
-require('sinon-as-promised')
 // add support for mongoose in sinon
 require('sinon-mongoose')
 
@@ -21,3 +19,7 @@ process.on('unhandledRejection', err => {
   console.error('Unhandled promise rejection:', err)
   process.exit(1)
 })
+
+afterEach(function() {
+  sinon.restore()
+})

+ 4 - 2
services/web/test/unit/src/Authorization/AuthorizationMiddlewareTests.js

@@ -115,7 +115,9 @@ describe('AuthorizationMiddleware', function() {
               this.res,
               this.next
             )
-            this.next.calledWith(new Error()).should.equal(true)
+            this.next
+              .calledWith(sinon.match.instanceOf(Error))
+              .should.equal(true)
           })
         })
 
@@ -242,7 +244,7 @@ describe('AuthorizationMiddleware', function() {
           this.res,
           this.next
         )
-        this.next.calledWith(new Error()).should.equal(true)
+        this.next.calledWith(sinon.match.instanceOf(Error)).should.equal(true)
       })
     })
 

+ 6 - 6
services/web/test/unit/src/Chat/ChatApiHandlerTests.js

@@ -96,9 +96,9 @@ describe('ChatApiHandler', function() {
       })
 
       it('should return an error', function() {
-        const error = new Error()
-        error.statusCode = 500
-        return this.callback.calledWith(error).should.equal(true)
+        expect(this.callback).to.have.been.calledWith(
+          sinon.match.instanceOf(Error).and(sinon.match.has('statusCode', 500))
+        )
       })
     })
   })
@@ -154,9 +154,9 @@ describe('ChatApiHandler', function() {
       })
 
       it('should return an error', function() {
-        const error = new Error()
-        error.statusCode = 500
-        return this.callback.calledWith(error).should.equal(true)
+        expect(this.callback).to.have.been.calledWith(
+          sinon.match.instanceOf(Error).and(sinon.match.has('statusCode', 500))
+        )
       })
     })
   })

+ 25 - 19
services/web/test/unit/src/Collaborators/CollaboratorsInviteControllerTests.js

@@ -164,7 +164,6 @@ describe('CollaboratorsInviteController', function() {
       this.CollaboratorsInviteHandler.inviteToProject = sinon
         .stub()
         .callsArgWith(4, null, this.invite)
-      this.err = new Error('woops')
       this.callback = sinon.stub()
       return (this.next = sinon.stub())
     })
@@ -283,7 +282,7 @@ describe('CollaboratorsInviteController', function() {
           .yields(null, true)
         this.LimitationsManager.canAddXCollaborators = sinon
           .stub()
-          .callsArgWith(2, this.err)
+          .callsArgWith(2, new Error('woops'))
         return this.CollaboratorsInviteController.inviteToProject(
           this.req,
           this.res,
@@ -293,7 +292,9 @@ describe('CollaboratorsInviteController', function() {
 
       it('should call next with an error', function() {
         this.next.callCount.should.equal(1)
-        return this.next.calledWith(this.err).should.equal(true)
+        return this.next
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
 
       it('should not have called _checkShouldInviteEmail', function() {
@@ -320,10 +321,9 @@ describe('CollaboratorsInviteController', function() {
         this.CollaboratorsInviteController._checkRateLimit = sinon
           .stub()
           .yields(null, true)
-        this.err = new Error('woops')
         this.CollaboratorsInviteHandler.inviteToProject = sinon
           .stub()
-          .callsArgWith(4, this.err)
+          .callsArgWith(4, new Error('woops'))
         return this.CollaboratorsInviteController.inviteToProject(
           this.req,
           this.res,
@@ -333,7 +333,7 @@ describe('CollaboratorsInviteController', function() {
 
       it('should call next with an error', function() {
         this.next.callCount.should.equal(1)
-        return this.next.calledWith(this.err).should.equal(true)
+        expect(this.next).to.have.been.calledWith(sinon.match.instanceOf(Error))
       })
 
       it('should have called canAddXCollaborators', function() {
@@ -429,7 +429,9 @@ describe('CollaboratorsInviteController', function() {
 
       it('should call next with an error', function() {
         this.next.callCount.should.equal(1)
-        return this.next.calledWith(this.err).should.equal(true)
+        return this.next
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
 
       it('should have called _checkShouldInviteEmail', function() {
@@ -729,10 +731,9 @@ describe('CollaboratorsInviteController', function() {
 
     describe('when the getInviteByToken produces an error', function() {
       beforeEach(function() {
-        this.err = new Error('woops')
         this.CollaboratorsInviteHandler.getInviteByToken.callsArgWith(
           2,
-          this.err
+          new Error('woops')
         )
         return this.CollaboratorsInviteController.viewInvite(
           this.req,
@@ -743,7 +744,9 @@ describe('CollaboratorsInviteController', function() {
 
       it('should call next with the error', function() {
         this.next.callCount.should.equal(1)
-        return this.next.calledWith(this.err).should.equal(true)
+        return this.next
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
 
       it('should call CollaboratorsGetter.isUserInvitedMemberOfProject', function() {
@@ -1056,10 +1059,9 @@ describe('CollaboratorsInviteController', function() {
 
     describe('when resendInvite produces an error', function() {
       beforeEach(function() {
-        this.err = new Error('woops')
         this.CollaboratorsInviteHandler.resendInvite = sinon
           .stub()
-          .callsArgWith(3, this.err)
+          .callsArgWith(3, new Error('woops'))
         return this.CollaboratorsInviteController.resendInvite(
           this.req,
           this.res,
@@ -1073,7 +1075,9 @@ describe('CollaboratorsInviteController', function() {
 
       it('should call next with the error', function() {
         this.next.callCount.should.equal(1)
-        return this.next.calledWith(this.err).should.equal(true)
+        return this.next
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
 
       it('should have called resendInvite', function() {
@@ -1131,10 +1135,9 @@ describe('CollaboratorsInviteController', function() {
 
     describe('when revokeInvite produces an error', function() {
       beforeEach(function() {
-        this.err = new Error('woops')
         this.CollaboratorsInviteHandler.revokeInvite = sinon
           .stub()
-          .callsArgWith(2, this.err)
+          .callsArgWith(2, new Error('woops'))
         return this.CollaboratorsInviteController.revokeInvite(
           this.req,
           this.res,
@@ -1148,7 +1151,9 @@ describe('CollaboratorsInviteController', function() {
 
       it('should call next with the error', function() {
         this.next.callCount.should.equal(1)
-        return this.next.calledWith(this.err).should.equal(true)
+        return this.next
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
 
       it('should have called revokeInvite', function() {
@@ -1209,10 +1214,9 @@ describe('CollaboratorsInviteController', function() {
 
     describe('when revokeInvite produces an error', function() {
       beforeEach(function() {
-        this.err = new Error('woops')
         this.CollaboratorsInviteHandler.acceptInvite = sinon
           .stub()
-          .callsArgWith(3, this.err)
+          .callsArgWith(3, new Error('woops'))
         return this.CollaboratorsInviteController.acceptInvite(
           this.req,
           this.res,
@@ -1226,7 +1230,9 @@ describe('CollaboratorsInviteController', function() {
 
       it('should call next with the error', function() {
         this.next.callCount.should.equal(1)
-        return this.next.calledWith(this.err).should.equal(true)
+        return this.next
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
 
       it('should have called acceptInvite', function() {

+ 37 - 15
services/web/test/unit/src/Contact/ContactManagerTests.js

@@ -97,23 +97,33 @@ describe('ContactManager', function() {
       it('should call the callback with an error', function() {
         return this.callback
           .calledWith(
-            new Error('contacts api responded with non-success code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'contacts api responded with non-success code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
 
       it('should log the error', function() {
-        return this.logger.warn
-          .calledWith(
-            {
-              err: new Error(
-                'contacts api responded with a non-success code: 500'
+        this.logger.warn.should.have.been.calledWith(
+          {
+            err: sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'contacts api responded with non-success code: 500'
+                )
               ),
-              user_id: this.user_id
-            },
-            'error getting contacts for user'
-          )
-          .should.equal(true)
+            user_id: this.user_id
+          },
+          'error getting contacts for user'
+        )
       })
     })
   })
@@ -165,7 +175,14 @@ describe('ContactManager', function() {
       it('should call the callback with an error', function() {
         return this.callback
           .calledWith(
-            new Error('contacts api responded with non-success code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'contacts api responded with non-success code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -174,9 +191,14 @@ describe('ContactManager', function() {
         return this.logger.warn
           .calledWith(
             {
-              err: new Error(
-                'contacts api responded with a non-success code: 500'
-              ),
+              err: sinon.match
+                .instanceOf(Error)
+                .and(
+                  sinon.match.has(
+                    'message',
+                    'contacts api responded with non-success code: 500'
+                  )
+                ),
               user_id: this.user_id,
               contact_id: this.contact_id
             },

+ 131 - 31
services/web/test/unit/src/Docstore/DocstoreManagerTests.js

@@ -39,7 +39,8 @@ describe('DocstoreManager', function() {
           warn: sinon.stub(),
           error: sinon.stub(),
           err() {}
-        })
+        }),
+        '../Errors/Errors': Errors
       }
     })
 
@@ -94,7 +95,14 @@ describe('DocstoreManager', function() {
       it('should call the callback with an error', function() {
         return this.callback
           .calledWith(
-            new Error('docstore api responded with non-success code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'docstore api responded with non-success code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -103,9 +111,14 @@ describe('DocstoreManager', function() {
         return this.logger.warn
           .calledWith(
             {
-              err: new Error(
-                'docstore api responded with a non-success code: 500'
-              ),
+              err: sinon.match
+                .instanceOf(Error)
+                .and(
+                  sinon.match.has(
+                    'message',
+                    'docstore api responded with non-success code: 500'
+                  )
+                ),
               project_id: this.project_id,
               doc_id: this.doc_id
             },
@@ -128,9 +141,16 @@ describe('DocstoreManager', function() {
       })
 
       it('should call the callback with an error', function() {
-        return this.callback
+        this.callback
           .calledWith(
-            new Errors.NotFoundError('tried to delete doc not in docstore')
+            sinon.match
+              .instanceOf(Errors.NotFoundError)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'tried to delete doc not in docstore'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -139,9 +159,14 @@ describe('DocstoreManager', function() {
         return this.logger.warn
           .calledWith(
             {
-              err: new Errors.NotFoundError(
-                'tried to delete doc not in docstore'
-              ),
+              err: sinon.match
+                .instanceOf(Errors.NotFoundError)
+                .and(
+                  sinon.match.has(
+                    'message',
+                    'tried to delete doc not in docstore'
+                  )
+                ),
               project_id: this.project_id,
               doc_id: this.doc_id
             },
@@ -222,7 +247,14 @@ describe('DocstoreManager', function() {
       it('should call the callback with an error', function() {
         return this.callback
           .calledWith(
-            new Error('docstore api responded with non-success code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'docstore api responded with non-success code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -231,9 +263,14 @@ describe('DocstoreManager', function() {
         return this.logger.warn
           .calledWith(
             {
-              err: new Error(
-                'docstore api responded with a non-success code: 500'
-              ),
+              err: sinon.match
+                .instanceOf(Error)
+                .and(
+                  sinon.match.has(
+                    'message',
+                    'docstore api responded with non-success code: 500'
+                  )
+                ),
               project_id: this.project_id,
               doc_id: this.doc_id
             },
@@ -300,7 +337,14 @@ describe('DocstoreManager', function() {
       it('should call the callback with an error', function() {
         return this.callback
           .calledWith(
-            new Error('docstore api responded with non-success code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'docstore api responded with non-success code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -309,9 +353,14 @@ describe('DocstoreManager', function() {
         return this.logger.warn
           .calledWith(
             {
-              err: new Error(
-                'docstore api responded with a non-success code: 500'
-              ),
+              err: sinon.match
+                .instanceOf(Error)
+                .and(
+                  sinon.match.has(
+                    'message',
+                    'docstore api responded with non-success code: 500'
+                  )
+                ),
               project_id: this.project_id,
               doc_id: this.doc_id
             },
@@ -367,7 +416,11 @@ describe('DocstoreManager', function() {
 
       it('should call the callback with an error', function() {
         return this.callback
-          .calledWith(new Errors.NotFoundError('doc not found in docstore'))
+          .calledWith(
+            sinon.match
+              .instanceOf(Errors.NotFoundError)
+              .and(sinon.match.has('message', 'doc not found in docstore'))
+          )
           .should.equal(true)
       })
 
@@ -375,7 +428,9 @@ describe('DocstoreManager', function() {
         return this.logger.warn
           .calledWith(
             {
-              err: new Errors.NotFoundError('doc not found in docstore'),
+              err: sinon.match
+                .instanceOf(Errors.NotFoundError)
+                .and(sinon.match.has('message', 'doc not found in docstore')),
               project_id: this.project_id,
               doc_id: this.doc_id
             },
@@ -428,7 +483,14 @@ describe('DocstoreManager', function() {
       it('should call the callback with an error', function() {
         return this.callback
           .calledWith(
-            new Error('docstore api responded with non-success code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'docstore api responded with non-success code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -437,9 +499,14 @@ describe('DocstoreManager', function() {
         return this.logger.warn
           .calledWith(
             {
-              err: new Error(
-                'docstore api responded with a non-success code: 500'
-              ),
+              err: sinon.match
+                .instanceOf(Error)
+                .and(
+                  sinon.match.has(
+                    'message',
+                    'docstore api responded with non-success code: 500'
+                  )
+                ),
               project_id: this.project_id
             },
             'error getting all docs from docstore'
@@ -491,7 +558,14 @@ describe('DocstoreManager', function() {
       it('should call the callback with an error', function() {
         return this.callback
           .calledWith(
-            new Error('docstore api responded with non-success code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'docstore api responded with non-success code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -500,9 +574,14 @@ describe('DocstoreManager', function() {
         return this.logger.warn
           .calledWith(
             {
-              err: new Error(
-                'docstore api responded with a non-success code: 500'
-              ),
+              err: sinon.match
+                .instanceOf(Error)
+                .and(
+                  sinon.match.has(
+                    'message',
+                    'docstore api responded with non-success code: 500'
+                  )
+                ),
               project_id: this.project_id
             },
             'error getting all doc ranges from docstore'
@@ -543,7 +622,14 @@ describe('DocstoreManager', function() {
       it('should call the callback with an error', function() {
         return this.callback
           .calledWith(
-            new Error('docstore api responded with non-success code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'docstore api responded with non-success code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -581,7 +667,14 @@ describe('DocstoreManager', function() {
       it('should call the callback with an error', function() {
         return this.callback
           .calledWith(
-            new Error('docstore api responded with non-success code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'docstore api responded with non-success code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -619,7 +712,14 @@ describe('DocstoreManager', function() {
       it('should call the callback with an error', function() {
         return this.callback
           .calledWith(
-            new Error('docstore api responded with non-success code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'docstore api responded with non-success code: 500'
+                )
+              )
           )
           .should.equal(true)
       })

+ 115 - 35
services/web/test/unit/src/DocumentUpdater/DocumentUpdaterHandlerTests.js

@@ -84,7 +84,7 @@ describe('DocumentUpdaterHandler', function() {
       beforeEach(function() {
         this.request.callsArgWith(
           1,
-          (this.error = new Error('something went wrong')),
+          new Error('something went wrong'),
           null,
           null
         )
@@ -92,7 +92,9 @@ describe('DocumentUpdaterHandler', function() {
       })
 
       it('should return an error to the callback', function() {
-        this.callback.calledWith(this.error).should.equal(true)
+        this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
 
@@ -105,7 +107,14 @@ describe('DocumentUpdaterHandler', function() {
       it('should return the callback with an error', function() {
         this.callback
           .calledWith(
-            new Error('doc updater returned failure status code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'document updater returned a failure status code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -142,7 +151,7 @@ describe('DocumentUpdaterHandler', function() {
       beforeEach(function() {
         this.request.callsArgWith(
           1,
-          (this.error = new Error('something went wrong')),
+          new Error('something went wrong'),
           null,
           null
         )
@@ -153,7 +162,9 @@ describe('DocumentUpdaterHandler', function() {
       })
 
       it('should return an error to the callback', function() {
-        this.callback.calledWith(this.error).should.equal(true)
+        this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
 
@@ -169,7 +180,14 @@ describe('DocumentUpdaterHandler', function() {
       it('should return the callback with an error', function() {
         this.callback
           .calledWith(
-            new Error('doc updater returned failure status code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'document updater returned a failure status code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -207,7 +225,7 @@ describe('DocumentUpdaterHandler', function() {
       beforeEach(function() {
         this.request.callsArgWith(
           1,
-          (this.error = new Error('something went wrong')),
+          new Error('something went wrong'),
           null,
           null
         )
@@ -219,7 +237,9 @@ describe('DocumentUpdaterHandler', function() {
       })
 
       it('should return an error to the callback', function() {
-        this.callback.calledWith(this.error).should.equal(true)
+        this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
 
@@ -236,7 +256,14 @@ describe('DocumentUpdaterHandler', function() {
       it('should return the callback with an error', function() {
         this.callback
           .calledWith(
-            new Error('doc updater returned failure status code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'document updater returned a failure status code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -270,7 +297,7 @@ describe('DocumentUpdaterHandler', function() {
       beforeEach(function() {
         this.request.callsArgWith(
           1,
-          (this.error = new Error('something went wrong')),
+          new Error('something went wrong'),
           null,
           null
         )
@@ -278,7 +305,9 @@ describe('DocumentUpdaterHandler', function() {
       })
 
       it('should return an error to the callback', function() {
-        this.callback.calledWith(this.error).should.equal(true)
+        this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
 
@@ -291,7 +320,14 @@ describe('DocumentUpdaterHandler', function() {
       it('should return the callback with an error', function() {
         this.callback
           .calledWith(
-            new Error('doc updater returned failure status code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'document updater returned a failure status code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -341,7 +377,7 @@ describe('DocumentUpdaterHandler', function() {
       beforeEach(function() {
         this.request.callsArgWith(
           1,
-          (this.error = new Error('something went wrong')),
+          new Error('something went wrong'),
           null,
           null
         )
@@ -356,7 +392,9 @@ describe('DocumentUpdaterHandler', function() {
       })
 
       it('should return an error to the callback', function() {
-        this.callback.calledWith(this.error).should.equal(true)
+        this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
 
@@ -376,7 +414,14 @@ describe('DocumentUpdaterHandler', function() {
       it('should return the callback with an error', function() {
         this.callback
           .calledWith(
-            new Error('doc updater returned failure status code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'document updater returned a failure status code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -425,7 +470,7 @@ describe('DocumentUpdaterHandler', function() {
       beforeEach(function() {
         this.request.callsArgWith(
           1,
-          (this.error = new Error('something went wrong')),
+          new Error('something went wrong'),
           null,
           null
         )
@@ -438,7 +483,9 @@ describe('DocumentUpdaterHandler', function() {
       })
 
       it('should return an error to the callback', function() {
-        this.callback.calledWith(this.error).should.equal(true)
+        this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
 
@@ -456,7 +503,14 @@ describe('DocumentUpdaterHandler', function() {
       it('should return the callback with an error', function() {
         this.callback
           .calledWith(
-            new Error('doc updater returned failure status code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'document updater returned a failure status code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -503,12 +557,7 @@ describe('DocumentUpdaterHandler', function() {
       beforeEach(function() {
         this.request.post = sinon
           .stub()
-          .callsArgWith(
-            1,
-            (this.error = new Error('something went wrong')),
-            null,
-            null
-          )
+          .callsArgWith(1, new Error('something went wrong'), null, null)
         this.handler.getProjectDocsIfMatch(
           this.project_id,
           this.project_state_hash,
@@ -517,7 +566,9 @@ describe('DocumentUpdaterHandler', function() {
       })
 
       it('should return an error to the callback', function() {
-        this.callback.calledWith(this.error).should.equal(true)
+        this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
 
@@ -566,7 +617,7 @@ describe('DocumentUpdaterHandler', function() {
       beforeEach(function() {
         this.request.callsArgWith(
           1,
-          (this.error = new Error('something went wrong')),
+          new Error('something went wrong'),
           null,
           null
         )
@@ -574,7 +625,9 @@ describe('DocumentUpdaterHandler', function() {
       })
 
       it('should return an error to the callback', function() {
-        this.callback.calledWith(this.error).should.equal(true)
+        this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
 
@@ -587,7 +640,14 @@ describe('DocumentUpdaterHandler', function() {
       it('should return the callback with no documents', function() {
         this.callback
           .calledWith(
-            new Error('doc updater returned failure status code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'document updater returned a failure status code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -633,7 +693,7 @@ describe('DocumentUpdaterHandler', function() {
       beforeEach(function() {
         this.request.callsArgWith(
           1,
-          (this.error = new Error('something went wrong')),
+          new Error('something went wrong'),
           null,
           null
         )
@@ -646,7 +706,9 @@ describe('DocumentUpdaterHandler', function() {
       })
 
       it('should return an error to the callback', function() {
-        this.callback.calledWith(this.error).should.equal(true)
+        this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
 
@@ -664,7 +726,14 @@ describe('DocumentUpdaterHandler', function() {
       it('should return the callback with an error', function() {
         this.callback
           .calledWith(
-            new Error('doc updater returned failure status code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'document updater returned a failure status code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -707,7 +776,7 @@ describe('DocumentUpdaterHandler', function() {
       beforeEach(function() {
         this.request.callsArgWith(
           1,
-          (this.error = new Error('something went wrong')),
+          new Error('something went wrong'),
           null,
           null
         )
@@ -720,7 +789,9 @@ describe('DocumentUpdaterHandler', function() {
       })
 
       it('should return an error to the callback', function() {
-        this.callback.calledWith(this.error).should.equal(true)
+        this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
 
@@ -738,7 +809,14 @@ describe('DocumentUpdaterHandler', function() {
       it('should return the callback with an error', function() {
         this.callback
           .calledWith(
-            new Error('doc updater returned failure status code: 500')
+            sinon.match
+              .instanceOf(Error)
+              .and(
+                sinon.match.has(
+                  'message',
+                  'document updater returned a failure status code: 500'
+                )
+              )
           )
           .should.equal(true)
       })
@@ -991,7 +1069,9 @@ describe('DocumentUpdaterHandler', function() {
             this.callback
           )
 
-          this.callback.calledWith(new Error()).should.equal(true)
+          this.callback
+            .calledWith(sinon.match.instanceOf(Error))
+            .should.equal(true)
           const firstCallArgs = this.callback.args[0]
           firstCallArgs[0].message.should.equal(
             'did not receive project version in changes'

+ 4 - 3
services/web/test/unit/src/Documents/DocumentControllerTests.js

@@ -37,7 +37,8 @@ describe('DocumentController', function() {
         '../Project/ProjectGetter': (this.ProjectGetter = {}),
         '../Project/ProjectLocator': (this.ProjectLocator = {}),
         '../Project/ProjectEntityHandler': (this.ProjectEntityHandler = {}),
-        '../Project/ProjectEntityUpdateHandler': (this.ProjectEntityUpdateHandler = {})
+        '../Project/ProjectEntityUpdateHandler': (this.ProjectEntityUpdateHandler = {}),
+        '../Errors/Errors': Errors
       }
     })
     this.res = new MockResponse()
@@ -142,7 +143,7 @@ describe('DocumentController', function() {
 
         it('should call next with the NotFoundError', function() {
           return this.next
-            .calledWith(new Errors.NotFoundError('not found'))
+            .calledWith(sinon.match.instanceOf(Errors.NotFoundError))
             .should.equal(true)
         })
       })
@@ -267,7 +268,7 @@ describe('DocumentController', function() {
 
       it('should call next with the NotFoundError', function() {
         return this.next
-          .calledWith(new Errors.NotFoundError('not found'))
+          .calledWith(sinon.match.instanceOf(Errors.NotFoundError))
           .should.equal(true)
       })
     })

+ 6 - 11
services/web/test/unit/src/Editor/EditorControllerTests.js

@@ -581,12 +581,9 @@ describe('EditorController', function() {
     })
 
     it('should delete the folder using the project entity handler', function() {
-      return this.ProjectEntityUpdateHandler.deleteEntity.calledWith(
-        this.project_id,
-        this.entity_id,
-        this.type,
-        this.user_id
-      ).should.equal.true
+      return this.ProjectEntityUpdateHandler.deleteEntity
+        .calledWith(this.project_id, this.entity_id, this.type, this.user_id)
+        .should.equal(true)
     })
 
     it('notify users an entity has been deleted', function() {
@@ -618,11 +615,9 @@ describe('EditorController', function() {
     })
 
     it('should delete the folder using the project entity handler', function() {
-      return this.ProjectEntityUpdateHandler.deleteEntityWithPath.calledWith(
-        this.project_id,
-        this.path,
-        this.user_id
-      ).should.equal.true
+      return this.ProjectEntityUpdateHandler.deleteEntityWithPath
+        .calledWith(this.project_id, this.path, this.user_id)
+        .should.equal(true)
     })
 
     it('notify users an entity has been deleted', function() {

+ 1 - 1
services/web/test/unit/src/Email/EmailSenderTests.js

@@ -117,7 +117,7 @@ describe('EmailSender', function() {
     it('should not check the rate limiter when there is no sendingUser_id', async function() {
       this.EmailSender.sendEmail(this.opts, () => {
         expect(this.sesClient.sendMail).to.have.been.called
-        expect(this.RateLimiter.addCount).not.to.have.been.called
+        expect(this.RateLimiter.promises.addCount).not.to.have.been.called
       })
     })
 

+ 3 - 3
services/web/test/unit/src/Errors/HttpErrorControllerTests.js

@@ -44,9 +44,9 @@ describe('HttpErrorController', function() {
       sinon.assert.calledOnce(this.logger.warn)
 
       const { url, method, userId } = this.logger.warn.lastCall.args[0]
-      expect(userId).to.not.be.defined
-      expect(method).to.not.be.defined
-      expect(url).to.not.be.defined
+      expect(userId).not.to.exist
+      expect(method).not.to.exist
+      expect(url).not.to.exist
     })
 
     it('logs url method and userId', function() {

+ 8 - 8
services/web/test/unit/src/Project/ProjectCollabratecDetailsTest.js

@@ -108,7 +108,7 @@ describe('ProjectCollabratecDetailsHandler', function() {
       })
 
       it('should not update', function() {
-        return expect(this.ProjectModel.update).not.to.have.beenCalled
+        return expect(this.ProjectModel.update).not.to.have.been.called
       })
 
       it('should callback with error', function() {
@@ -193,7 +193,7 @@ describe('ProjectCollabratecDetailsHandler', function() {
       })
 
       it('should not update', function() {
-        return expect(this.ProjectModel.findOne).not.to.have.beenCalled
+        return expect(this.ProjectModel.findOne).not.to.have.been.called
       })
 
       it('should callback with error', function() {
@@ -270,7 +270,7 @@ describe('ProjectCollabratecDetailsHandler', function() {
       })
 
       it('should not update', function() {
-        return expect(this.ProjectModel.update).not.to.have.beenCalled
+        return expect(this.ProjectModel.update).not.to.have.been.called
       })
 
       it('should callback with error', function() {
@@ -345,7 +345,7 @@ describe('ProjectCollabratecDetailsHandler', function() {
       })
 
       it('should not update', function() {
-        return expect(this.ProjectModel.update).not.to.have.beenCalled
+        return expect(this.ProjectModel.update).not.to.have.been.called
       })
 
       it('should callback with error', function() {
@@ -365,7 +365,7 @@ describe('ProjectCollabratecDetailsHandler', function() {
       })
 
       it('should not update', function() {
-        return expect(this.ProjectModel.update).not.to.have.beenCalled
+        return expect(this.ProjectModel.update).not.to.have.been.called
       })
 
       it('should callback with error', function() {
@@ -428,7 +428,7 @@ describe('ProjectCollabratecDetailsHandler', function() {
       })
 
       it('should not update', function() {
-        return expect(this.ProjectModel.update).not.to.have.beenCalled
+        return expect(this.ProjectModel.update).not.to.have.been.called
       })
 
       it('should callback with error', function() {
@@ -484,7 +484,7 @@ describe('ProjectCollabratecDetailsHandler', function() {
       })
 
       it('should not update', function() {
-        return expect(this.ProjectModel.update).not.to.have.beenCalled
+        return expect(this.ProjectModel.update).not.to.have.been.called
       })
 
       it('should callback with error', function() {
@@ -503,7 +503,7 @@ describe('ProjectCollabratecDetailsHandler', function() {
       })
 
       it('should not update', function() {
-        return expect(this.ProjectModel.update).not.to.have.beenCalled
+        return expect(this.ProjectModel.update).not.to.have.been.called
       })
 
       it('should callback with error', function() {

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

@@ -1247,7 +1247,7 @@ describe('ProjectController', function() {
         this.user._id
       )
       expect(result).to.exist
-      expect(result).to.be.object
+      expect(result).to.be.an('object')
       expect(result).to.deep.equal({
         id: 'abcd',
         name: 'netsenits',
@@ -1276,7 +1276,7 @@ describe('ProjectController', function() {
           this.user._id
         )
         expect(result).to.exist
-        expect(result).to.be.object
+        expect(result).to.be.an('object')
         expect(result).to.deep.equal({
           id: 'abcd',
           name: 'netsenits',

+ 7 - 6
services/web/test/unit/src/Project/ProjectDetailsHandlerTests.js

@@ -39,10 +39,11 @@ describe('ProjectDetailsHandler', function() {
         })
       }
     }
+    this.ProjectModelUpdateQuery = {
+      exec: sinon.stub().resolves()
+    }
     this.ProjectModel = {
-      update: sinon.stub().returns({
-        exec: sinon.stub().resolves()
-      })
+      update: sinon.stub().returns(this.ProjectModelUpdateQuery)
     }
     this.UserGetter = {
       promises: {
@@ -221,7 +222,7 @@ describe('ProjectDetailsHandler', function() {
 
     it('should accept normal names', async function() {
       await expect(this.handler.promises.validateProjectName('foobar')).to.be
-        .resolved
+        .fulfilled
     })
   })
 
@@ -412,12 +413,12 @@ describe('ProjectDetailsHandler', function() {
           this.project._id,
           this.accessLevel
         )
-      ).to.be.resolved
+      ).to.be.fulfilled
     })
 
     describe('when update produces an error', function() {
       beforeEach(function() {
-        this.ProjectModel.update.rejects(new Error('woops'))
+        this.ProjectModelUpdateQuery.exec.rejects(new Error('woops'))
       })
 
       it('should produce an error', async function() {

+ 43 - 47
services/web/test/unit/src/Project/ProjectEntityMongoUpdateHandlerTests.js

@@ -61,7 +61,8 @@ describe('ProjectEntityMongoUpdateHandler', function() {
         './ProjectLocator': (this.ProjectLocator = {}),
         './ProjectGetter': (this.ProjectGetter = {
           getProjectWithoutLock: sinon.stub().yields(null, this.project)
-        })
+        }),
+        '../Errors/Errors': Errors
       }
     })
   })
@@ -234,16 +235,18 @@ describe('ProjectEntityMongoUpdateHandler', function() {
         .stub()
         .yields(null, this.project)
       this.ProjectLocator.findElementByPath = function() {}
-      sinon.stub(this.ProjectLocator, 'findElementByPath', (options, cb) => {
-        const { path } = options
-        this.parentFolder = { _id: 'parentFolder_id_here' }
-        const lastFolder = path.substring(path.lastIndexOf('/'))
-        if (lastFolder.indexOf('level1') === -1) {
-          cb(new Error('level1 is not the last folder'))
-        } else {
-          cb(null, this.parentFolder)
-        }
-      })
+      sinon
+        .stub(this.ProjectLocator, 'findElementByPath')
+        .callsFake((options, cb) => {
+          const { path } = options
+          this.parentFolder = { _id: 'parentFolder_id_here' }
+          const lastFolder = path.substring(path.lastIndexOf('/'))
+          if (lastFolder.indexOf('level1') === -1) {
+            cb(new Error('level1 is not the last folder'))
+          } else {
+            cb(null, this.parentFolder)
+          }
+        })
       this.subject.addFolder = {
         withoutLock: (projectId, parentFolderId, folderName, callback) => {
           return callback(null, { name: folderName }, this.parentFolderId)
@@ -528,7 +531,7 @@ describe('ProjectEntityMongoUpdateHandler', function() {
     })
 
     it('calls the callback with an error', function() {
-      this.callback.calledWith(new Error()).should.equal(true)
+      this.callback.calledWith(sinon.match.instanceOf(Error)).should.equal(true)
     })
   })
 
@@ -977,9 +980,8 @@ describe('ProjectEntityMongoUpdateHandler', function() {
           'doc',
           err => {
             this.ProjectModel.findOneAndUpdate.called.should.equal(false)
-            err.should.deep.equal(
-              new Errors.InvalidNameError('invalid element name')
-            )
+            expect(err).to.be.instanceOf(Errors.InvalidNameError)
+            expect(err).to.have.property('message', 'invalid element name')
             done()
           }
         )
@@ -997,9 +999,8 @@ describe('ProjectEntityMongoUpdateHandler', function() {
           'doc',
           err => {
             this.ProjectModel.findOneAndUpdate.called.should.equal(false)
-            err.should.deep.equal(
-              new Errors.InvalidNameError('invalid element name')
-            )
+            expect(err).to.be.instanceOf(Errors.InvalidNameError)
+            expect(err).to.have.property('message', 'path too long')
             done()
           }
         )
@@ -1027,7 +1028,8 @@ describe('ProjectEntityMongoUpdateHandler', function() {
           'doc',
           err => {
             this.ProjectModel.findOneAndUpdate.called.should.equal(false)
-            err.should.deep.equal(new Errors.InvalidNameError('path too long'))
+            expect(err).to.be.instanceOf(Errors.InvalidNameError)
+            expect(err).to.have.property('message', 'path too long')
             done()
           }
         )
@@ -1040,9 +1042,8 @@ describe('ProjectEntityMongoUpdateHandler', function() {
         }
         this.subject._putElement(this.project, this.folder, doc, 'doc', err => {
           this.ProjectModel.findOneAndUpdate.called.should.equal(false)
-          err.should.deep.equal(
-            new Errors.InvalidNameError('file already exists')
-          )
+          expect(err).to.be.instanceOf(Errors.InvalidNameError)
+          expect(err).to.have.property('message', 'file already exists')
           done()
         })
       })
@@ -1054,9 +1055,8 @@ describe('ProjectEntityMongoUpdateHandler', function() {
         }
         this.subject._putElement(this.project, this.folder, doc, 'doc', err => {
           this.ProjectModel.findOneAndUpdate.called.should.equal(false)
-          err.should.deep.equal(
-            new Errors.InvalidNameError('file already exists')
-          )
+          expect(err).to.be.instanceOf(Errors.InvalidNameError)
+          expect(err).to.have.property('message', 'file already exists')
           done()
         })
       })
@@ -1068,9 +1068,8 @@ describe('ProjectEntityMongoUpdateHandler', function() {
         }
         this.subject._putElement(this.project, this.folder, doc, 'doc', err => {
           this.ProjectModel.findOneAndUpdate.called.should.equal(false)
-          err.should.deep.equal(
-            new Errors.InvalidNameError('file already exists')
-          )
+          expect(err).to.be.instanceOf(Errors.InvalidNameError)
+          expect(err).to.have.property('message', 'file already exists')
           done()
         })
       })
@@ -1087,27 +1086,24 @@ describe('ProjectEntityMongoUpdateHandler', function() {
     })
 
     it('returns an error if name matches any doc name', function() {
-      this.subject._checkValidElementName(this.folder, 'doc_name', err =>
-        expect(err).to.deep.equal(
-          new Errors.InvalidNameError('file already exists')
-        )
-      )
+      this.subject._checkValidElementName(this.folder, 'doc_name', err => {
+        expect(err).to.be.instanceOf(Errors.InvalidNameError)
+        expect(err).to.have.property('message', 'file already exists')
+      })
     })
 
     it('returns an error if name matches any file name', function() {
-      this.subject._checkValidElementName(this.folder, 'file_name', err =>
-        expect(err).to.deep.equal(
-          new Errors.InvalidNameError('file already exists')
-        )
-      )
+      this.subject._checkValidElementName(this.folder, 'file_name', err => {
+        expect(err).to.be.instanceOf(Errors.InvalidNameError)
+        expect(err).to.have.property('message', 'file already exists')
+      })
     })
 
     it('returns an error if name matches any folder name', function() {
-      this.subject._checkValidElementName(this.folder, 'folder_name', err =>
-        expect(err).to.deep.equal(
-          new Errors.InvalidNameError('file already exists')
-        )
-      )
+      this.subject._checkValidElementName(this.folder, 'folder_name', err => {
+        expect(err).to.be.instanceOf(Errors.InvalidNameError)
+        expect(err).to.have.property('message', 'file already exists')
+      })
     })
 
     it('returns nothing if name is valid', function() {
@@ -1155,10 +1151,10 @@ describe('ProjectEntityMongoUpdateHandler', function() {
         { fileSystem: '/foo' },
         this.destFolder._id,
         err => {
-          expect(err).to.deep.equal(
-            new Errors.InvalidNameError(
-              'destination folder is a child folder of me'
-            )
+          expect(err).to.be.instanceOf(Errors.InvalidNameError)
+          expect(err).to.have.property(
+            'message',
+            'destination folder is a child folder of me'
           )
         }
       )

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

@@ -464,7 +464,7 @@ describe('ProjectEntityUpdateHandler', function() {
 
       it('should return a not found error', function() {
         return this.callback
-          .calledWith(new Errors.NotFoundError())
+          .calledWith(sinon.match.instanceOf(Errors.NotFoundError))
           .should.equal(true)
       })
     })
@@ -486,7 +486,7 @@ describe('ProjectEntityUpdateHandler', function() {
 
       it('should return a not found error', function() {
         return this.callback
-          .calledWith(new Errors.NotFoundError())
+          .calledWith(sinon.match.instanceOf(Errors.NotFoundError))
           .should.equal(true)
       })
     })
@@ -562,12 +562,12 @@ describe('ProjectEntityUpdateHandler', function() {
       beforeEach(function() {
         this.path = '/path/to/doc'
 
-        this.newDoc = {
+        this.newDoc = new this.DocModel({
           name: this.docName,
           lines: undefined,
           _id: doc_id,
           rev: 0
-        }
+        })
         this.DocstoreManager.updateDoc = sinon
           .stub()
           .yields(null, false, (this.rev = 5))
@@ -599,7 +599,7 @@ describe('ProjectEntityUpdateHandler', function() {
             docLines: this.docLines.join('\n')
           }
         ]
-        return this.DocumentUpdaterHandler.updateProjectStructure
+        this.DocumentUpdaterHandler.updateProjectStructure
           .calledWith(project_id, projectHistoryId, userId, {
             newDocs,
             newProject: this.project
@@ -1459,7 +1459,7 @@ describe('ProjectEntityUpdateHandler', function() {
 
       it('returns an error', function() {
         return this.callback
-          .calledWith(new Errors.NotFoundError())
+          .calledWith(sinon.match.instanceOf(Errors.NotFoundError))
           .should.equal(true)
       })
     })
@@ -1716,10 +1716,16 @@ describe('ProjectEntityUpdateHandler', function() {
       })
 
       it('should return an error', function() {
-        const error = new Errors.ProjectHistoryDisabledError(
-          `project history not enabled for ${project_id}`
+        expect(this.callback).to.have.been.calledWith(
+          sinon.match
+            .instanceOf(Errors.ProjectHistoryDisabledError)
+            .and(
+              sinon.match.has(
+                'message',
+                `project history not enabled for ${project_id}`
+              )
+            )
         )
-        return this.callback.calledWith(error).should.equal(true)
       })
     })
 
@@ -1735,10 +1741,16 @@ describe('ProjectEntityUpdateHandler', function() {
       })
 
       it('should return an error', function() {
-        const error = new Errors.ProjectHistoryDisabledError(
-          `project history not enabled for ${project_id}`
+        expect(this.callback).to.have.been.calledWith(
+          sinon.match
+            .instanceOf(Errors.ProjectHistoryDisabledError)
+            .and(
+              sinon.match.has(
+                'message',
+                `project history not enabled for ${project_id}`
+              )
+            )
         )
-        return this.callback.calledWith(error).should.equal(true)
       })
     })
 

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

@@ -98,7 +98,7 @@ describe('ProjectHistoryHandler', function() {
       })
 
       it('should initialize a new history in the v1 history service', function() {
-        return this.HistoryManager.initializeProject.called.should.equal.true
+        return this.HistoryManager.initializeProject.called.should.equal(true)
       })
 
       it('should set the new history id on the project', function() {

+ 3 - 3
services/web/test/unit/src/Project/ProjectLocatorTests.js

@@ -58,6 +58,7 @@ describe('ProjectLocator', function() {
       requires: {
         '../../models/Project': { Project },
         '../../models/User': { User: this.User },
+        '../Errors/Errors': Errors,
         './ProjectGetter': this.ProjectGetter,
         './ProjectHelper': this.ProjectHelper,
         'logger-sharelatex': {
@@ -108,9 +109,8 @@ describe('ProjectLocator', function() {
       this.locator.findElement(
         { project_id: project._id, element_id: 'ddsd432nj42', type: 'docs' },
         (err, foundElement, path, parentFolder) => {
-          expect(err).to.deep.equal(
-            new Errors.NotFoundError('entity not found')
-          )
+          expect(err).to.be.instanceOf(Errors.NotFoundError)
+          expect(err).to.have.property('message', 'entity not found')
           done()
         }
       )

+ 10 - 2
services/web/test/unit/src/Project/ProjectRootDocManagerTests.js

@@ -563,7 +563,11 @@ describe('ProjectRootDocManager', function() {
 
       it('should call the callback with an error', function() {
         return this.callback
-          .calledWith(new Error('project not found'))
+          .calledWith(
+            sinon.match
+              .instanceOf(Error)
+              .and(sinon.match.has('message', 'project not found'))
+          )
           .should.equal(true)
       })
     })
@@ -681,7 +685,11 @@ describe('ProjectRootDocManager', function() {
 
       it('should call the callback with an error', function() {
         return this.callback
-          .calledWith(new Error('project not found'))
+          .calledWith(
+            sinon.match
+              .instanceOf(Error)
+              .and(sinon.match.has('message', 'project not found'))
+          )
           .should.equal(true)
       })
     })

+ 2 - 6
services/web/test/unit/src/Project/ProjectUpdateHandlerTests.js

@@ -19,9 +19,9 @@ const modulePath =
 const SandboxedModule = require('sandboxed-module')
 
 describe('ProjectUpdateHandler', function() {
-  before(function() {
+  beforeEach(function() {
     this.fakeTime = new Date()
-    return (this.clock = sinon.useFakeTimers(this.fakeTime.getTime()))
+    this.clock = sinon.useFakeTimers(this.fakeTime.getTime())
   })
 
   beforeEach(function() {
@@ -39,10 +39,6 @@ describe('ProjectUpdateHandler', function() {
     }))
   })
 
-  after(function() {
-    return this.clock.restore()
-  })
-
   describe('marking a project as recently updated', function() {
     beforeEach(function() {
       this.project_id = 'project_id'

+ 5 - 1
services/web/test/unit/src/Security/SessionStoreManagerTests.js

@@ -71,7 +71,11 @@ describe('SessionStoreManager', function() {
         this.next
       )
       expect(this.req.session.destroy).to.be.called
-      expect(this.next).to.be.calledWithExactly(new Error('invalid session'))
+      expect(this.next).to.be.calledWithExactly(
+        sinon.match
+          .instanceOf(Error)
+          .and(sinon.match.has('message', 'invalid session'))
+      )
     })
     it('should accept the request when the session does not have a validation token', function() {
       this.req = { sessionID: '123456789', session: {} }

+ 49 - 42
services/web/test/unit/src/Subscription/LimitationsManagerTests.js

@@ -158,13 +158,14 @@ describe('LimitationsManager', function() {
           project_id,
           callback
         ) => callback(null, this.invite_count)
-        sinon.stub(
-          this.LimitationsManager,
-          'allowedNumberOfCollaboratorsInProject',
-          (project_id, callback) => {
+        sinon
+          .stub(
+            this.LimitationsManager,
+            'allowedNumberOfCollaboratorsInProject'
+          )
+          .callsFake((project_id, callback) => {
             return callback(null, this.allowed_number)
-          }
-        )
+          })
         this.callback = sinon.stub()
         return this.LimitationsManager.canAddXCollaborators(
           this.project_id,
@@ -191,13 +192,14 @@ describe('LimitationsManager', function() {
           project_id,
           callback
         ) => callback(null, this.invite_count)
-        sinon.stub(
-          this.LimitationsManager,
-          'allowedNumberOfCollaboratorsInProject',
-          (project_id, callback) => {
+        sinon
+          .stub(
+            this.LimitationsManager,
+            'allowedNumberOfCollaboratorsInProject'
+          )
+          .callsFake((project_id, callback) => {
             return callback(null, this.allowed_number)
-          }
-        )
+          })
         this.callback = sinon.stub()
         return this.LimitationsManager.canAddXCollaborators(
           this.project_id,
@@ -224,13 +226,14 @@ describe('LimitationsManager', function() {
           project_id,
           callback
         ) => callback(null, this.invite_count)
-        sinon.stub(
-          this.LimitationsManager,
-          'allowedNumberOfCollaboratorsInProject',
-          (project_id, callback) => {
+        sinon
+          .stub(
+            this.LimitationsManager,
+            'allowedNumberOfCollaboratorsInProject'
+          )
+          .callsFake((project_id, callback) => {
             return callback(null, this.allowed_number)
-          }
-        )
+          })
         this.callback = sinon.stub()
         return this.LimitationsManager.canAddXCollaborators(
           this.project_id,
@@ -257,13 +260,14 @@ describe('LimitationsManager', function() {
           project_id,
           callback
         ) => callback(null, this.invite_count)
-        sinon.stub(
-          this.LimitationsManager,
-          'allowedNumberOfCollaboratorsInProject',
-          (project_id, callback) => {
+        sinon
+          .stub(
+            this.LimitationsManager,
+            'allowedNumberOfCollaboratorsInProject'
+          )
+          .callsFake((project_id, callback) => {
             return callback(null, this.allowed_number)
-          }
-        )
+          })
         this.callback = sinon.stub()
         return this.LimitationsManager.canAddXCollaborators(
           this.project_id,
@@ -290,13 +294,14 @@ describe('LimitationsManager', function() {
           project_id,
           callback
         ) => callback(null, this.invite_count)
-        sinon.stub(
-          this.LimitationsManager,
-          'allowedNumberOfCollaboratorsInProject',
-          (project_id, callback) => {
+        sinon
+          .stub(
+            this.LimitationsManager,
+            'allowedNumberOfCollaboratorsInProject'
+          )
+          .callsFake((project_id, callback) => {
             return callback(null, this.allowed_number)
-          }
-        )
+          })
         this.callback = sinon.stub()
         return this.LimitationsManager.canAddXCollaborators(
           this.project_id,
@@ -323,13 +328,14 @@ describe('LimitationsManager', function() {
           project_id,
           callback
         ) => callback(null, this.invite_count)
-        sinon.stub(
-          this.LimitationsManager,
-          'allowedNumberOfCollaboratorsInProject',
-          (project_id, callback) => {
+        sinon
+          .stub(
+            this.LimitationsManager,
+            'allowedNumberOfCollaboratorsInProject'
+          )
+          .callsFake((project_id, callback) => {
             return callback(null, this.allowed_number)
-          }
-        )
+          })
         this.callback = sinon.stub()
         return this.LimitationsManager.canAddXCollaborators(
           this.project_id,
@@ -356,13 +362,14 @@ describe('LimitationsManager', function() {
           project_id,
           callback
         ) => callback(null, this.invite_count)
-        sinon.stub(
-          this.LimitationsManager,
-          'allowedNumberOfCollaboratorsInProject',
-          (project_id, callback) => {
+        sinon
+          .stub(
+            this.LimitationsManager,
+            'allowedNumberOfCollaboratorsInProject'
+          )
+          .callsFake((project_id, callback) => {
             return callback(null, this.allowed_number)
-          }
-        )
+          })
         this.callback = sinon.stub()
         return this.LimitationsManager.canAddXCollaborators(
           this.project_id,

+ 39 - 57
services/web/test/unit/src/Subscription/RecurlyWrapperTests.js

@@ -116,7 +116,7 @@ const mockApiRequest = function(options, callback) {
 }
 
 describe('RecurlyWrapper', function() {
-  before(function() {
+  beforeEach(function() {
     let RecurlyWrapper
     this.settings = {
       plans: [
@@ -164,18 +164,16 @@ describe('RecurlyWrapper', function() {
     ))
   })
 
-  after(function() {
+  afterEach(function() {
     return tk.reset()
   })
 
   describe('getSubscription', function() {
     describe('with proper subscription id', function() {
-      before(function() {
-        this.apiRequest = sinon.stub(
-          this.RecurlyWrapper,
-          'apiRequest',
-          mockApiRequest
-        )
+      beforeEach(function() {
+        this.apiRequest = sinon
+          .stub(this.RecurlyWrapper, 'apiRequest')
+          .callsFake(mockApiRequest)
         return this.RecurlyWrapper.getSubscription(
           '44f83d7cba354d5b84812419f923ea96',
           (error, recurlySubscription) => {
@@ -183,7 +181,7 @@ describe('RecurlyWrapper', function() {
           }
         )
       })
-      after(function() {
+      afterEach(function() {
         return this.RecurlyWrapper.apiRequest.restore()
       })
 
@@ -201,12 +199,10 @@ describe('RecurlyWrapper', function() {
     })
 
     describe('with ReculyJS token', function() {
-      before(function() {
-        this.apiRequest = sinon.stub(
-          this.RecurlyWrapper,
-          'apiRequest',
-          mockApiRequest
-        )
+      beforeEach(function() {
+        this.apiRequest = sinon
+          .stub(this.RecurlyWrapper, 'apiRequest')
+          .callsFake(mockApiRequest)
         return this.RecurlyWrapper.getSubscription(
           '70db44b10f5f4b238669480c9903f6f5',
           { recurlyJsResult: true },
@@ -215,7 +211,7 @@ describe('RecurlyWrapper', function() {
           }
         )
       })
-      after(function() {
+      afterEach(function() {
         return this.RecurlyWrapper.apiRequest.restore()
       })
 
@@ -234,11 +230,9 @@ describe('RecurlyWrapper', function() {
 
     describe('with includeAccount', function() {
       beforeEach(function() {
-        this.apiRequest = sinon.stub(
-          this.RecurlyWrapper,
-          'apiRequest',
-          mockApiRequest
-        )
+        this.apiRequest = sinon
+          .stub(this.RecurlyWrapper, 'apiRequest')
+          .callsFake(mockApiRequest)
         return this.RecurlyWrapper.getSubscription(
           '44f83d7cba354d5b84812419f923ea96',
           { includeAccount: true },
@@ -264,18 +258,16 @@ describe('RecurlyWrapper', function() {
   describe('updateSubscription', function() {
     beforeEach(function(done) {
       this.recurlySubscriptionId = 'subscription-id-123'
-      this.apiRequest = sinon.stub(
-        this.RecurlyWrapper,
-        'apiRequest',
-        (options, callback) => {
+      this.apiRequest = sinon
+        .stub(this.RecurlyWrapper, 'apiRequest')
+        .callsFake((options, callback) => {
           this.requestOptions = options
           return callback(
             null,
             {},
             fixtures['subscriptions/44f83d7cba354d5b84812419f923ea96']
           )
-        }
-      )
+        })
       return this.RecurlyWrapper.updateSubscription(
         this.recurlySubscriptionId,
         { plan_code: 'silver', timeframe: 'now' },
@@ -313,17 +305,15 @@ describe('RecurlyWrapper', function() {
   describe('cancelSubscription', function() {
     beforeEach(function(done) {
       this.recurlySubscriptionId = 'subscription-id-123'
-      this.apiRequest = sinon.stub(
-        this.RecurlyWrapper,
-        'apiRequest',
-        (options, callback) => {
+      this.apiRequest = sinon
+        .stub(this.RecurlyWrapper, 'apiRequest')
+        .callsFake((options, callback) => {
           options.url.should.equal(
             `subscriptions/${this.recurlySubscriptionId}/cancel`
           )
           options.method.should.equal('put')
           return callback()
-        }
-      )
+        })
       return this.RecurlyWrapper.cancelSubscription(
         this.recurlySubscriptionId,
         done
@@ -342,17 +332,15 @@ describe('RecurlyWrapper', function() {
       beforeEach(function() {
         this.RecurlyWrapper.apiRequest.restore()
         this.recurlySubscriptionId = 'subscription-id-123'
-        return (this.apiRequest = sinon.stub(
-          this.RecurlyWrapper,
-          'apiRequest',
-          (options, callback) => {
+        return (this.apiRequest = sinon
+          .stub(this.RecurlyWrapper, 'apiRequest')
+          .callsFake((options, callback) => {
             return callback(
               new Error('woops'),
               {},
               "<error><description>A canceled subscription can't transition to canceled</description></error>"
             )
-          }
-        ))
+          }))
       })
 
       it('should not produce an error', function(done) {
@@ -370,17 +358,15 @@ describe('RecurlyWrapper', function() {
   describe('reactivateSubscription', function() {
     beforeEach(function(done) {
       this.recurlySubscriptionId = 'subscription-id-123'
-      this.apiRequest = sinon.stub(
-        this.RecurlyWrapper,
-        'apiRequest',
-        (options, callback) => {
+      this.apiRequest = sinon
+        .stub(this.RecurlyWrapper, 'apiRequest')
+        .callsFake((options, callback) => {
           options.url.should.equal(
             `subscriptions/${this.recurlySubscriptionId}/reactivate`
           )
           options.method.should.equal('put')
           return callback()
-        }
-      )
+        })
       return this.RecurlyWrapper.reactivateSubscription(
         this.recurlySubscriptionId,
         done
@@ -400,15 +386,13 @@ describe('RecurlyWrapper', function() {
     beforeEach(function(done) {
       this.recurlyAccountId = 'account-id-123'
       this.coupon_code = '312321312'
-      this.apiRequest = sinon.stub(
-        this.RecurlyWrapper,
-        'apiRequest',
-        (options, callback) => {
+      this.apiRequest = sinon
+        .stub(this.RecurlyWrapper, 'apiRequest')
+        .callsFake((options, callback) => {
           options.url.should.equal(`coupons/${this.coupon_code}/redeem`)
           options.method.should.equal('post')
           return callback()
-        }
-      )
+        })
       return this.RecurlyWrapper.redeemCoupon(
         this.recurlyAccountId,
         this.coupon_code,
@@ -439,13 +423,11 @@ describe('RecurlyWrapper', function() {
       this.currencyCode = 'EUR'
       this.discount = 1337
       this.planCode = 'a-plan-code'
-      this.apiRequest = sinon.stub(
-        this.RecurlyWrapper,
-        'apiRequest',
-        (options, callback) => {
+      this.apiRequest = sinon
+        .stub(this.RecurlyWrapper, 'apiRequest')
+        .callsFake((options, callback) => {
           return callback()
-        }
-      )
+        })
       return this.RecurlyWrapper.createFixedAmmountCoupon(
         this.couponCode,
         this.couponName,

+ 18 - 6
services/web/test/unit/src/Tags/TagsHandlerTests.js

@@ -216,7 +216,9 @@ describe('TagsHandler', function() {
       })
 
       it('should call the callback with an Error', function() {
-        return this.callback.calledWith(new Error()).should.equal(true)
+        return this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
   })
@@ -261,7 +263,9 @@ describe('TagsHandler', function() {
       })
 
       it('should call the callback with an Error', function() {
-        return this.callback.calledWith(new Error()).should.equal(true)
+        return this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
   })
@@ -308,7 +312,9 @@ describe('TagsHandler', function() {
       })
 
       it('should call the callback with an Error', function() {
-        return this.callback.calledWith(new Error()).should.equal(true)
+        return this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
   })
@@ -355,7 +361,9 @@ describe('TagsHandler', function() {
       })
 
       it('should call the callback with an Error', function() {
-        return this.callback.calledWith(new Error()).should.equal(true)
+        return this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
   })
@@ -405,7 +413,9 @@ describe('TagsHandler', function() {
       })
 
       it('should call the callback with an Error', function() {
-        return this.callback.calledWith(new Error()).should.equal(true)
+        return this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
   })
@@ -453,7 +463,9 @@ describe('TagsHandler', function() {
       })
 
       it('should call the callback with an Error', function() {
-        return this.callback.calledWith(new Error()).should.equal(true)
+        return this.callback
+          .calledWith(sinon.match.instanceOf(Error))
+          .should.equal(true)
       })
     })
   })

+ 13 - 10
services/web/test/unit/src/TokenAccess/TokenAccessControllerTests.js

@@ -72,7 +72,8 @@ describe('TokenAccessController', function() {
         },
         '../V1/V1Api': (this.V1Api = {
           request: sinon.stub().callsArgWith(1, null, {}, { allow: true })
-        })
+        }),
+        '../Errors/Errors': Errors
       }
     })
 
@@ -668,9 +669,11 @@ describe('TokenAccessController', function() {
 
             it('should call next with a not-found error', function(done) {
               expect(this.next.callCount).to.equal(1)
-              expect(this.next.calledWith(new Errors.NotFoundError())).to.equal(
-                true
-              )
+              expect(
+                this.next.calledWith(
+                  sinon.match.instanceOf(Errors.NotFoundError)
+                )
+              ).to.equal(true)
               return done()
             })
           })
@@ -1747,9 +1750,9 @@ describe('TokenAccessController', function() {
 
           it('should call next with not found error', function(done) {
             expect(this.next.callCount).to.equal(1)
-            expect(this.next.calledWith(new Errors.NotFoundError())).to.equal(
-              true
-            )
+            expect(
+              this.next.calledWith(sinon.match.instanceOf(Errors.NotFoundError))
+            ).to.equal(true)
             return done()
           })
         })
@@ -1796,9 +1799,9 @@ describe('TokenAccessController', function() {
 
           it('should call next with not found error', function(done) {
             expect(this.next.callCount).to.equal(1)
-            expect(this.next.calledWith(new Errors.NotFoundError())).to.equal(
-              true
-            )
+            expect(
+              this.next.calledWith(sinon.match.instanceOf(Errors.NotFoundError))
+            ).to.equal(true)
             return done()
           })
         })

+ 28 - 23
services/web/test/unit/src/Uploads/ArchiveManagerTests.js

@@ -17,11 +17,7 @@ const { expect } = require('chai')
 const chai = require('chai')
 const should = chai.should()
 const modulePath = '../../../../app/src/Features/Uploads/ArchiveManager.js'
-const {
-  InvalidZipFileError,
-  EmptyZipFileError,
-  ZipContentsTooLargeError
-} = require('../../../../app/src/Features/Uploads/ArchiveErrors')
+const ArchiveErrors = require('../../../../app/src/Features/Uploads/ArchiveErrors')
 const SandboxedModule = require('sandboxed-module')
 const events = require('events')
 
@@ -60,7 +56,8 @@ describe('ArchiveManager', function() {
         'logger-sharelatex': this.logger,
         'metrics-sharelatex': this.metrics,
         fs: (this.fs = {}),
-        'fs-extra': (this.fse = {})
+        'fs-extra': (this.fse = {}),
+        './ArchiveErrors': ArchiveErrors
       }
     })
     return (this.callback = sinon.stub())
@@ -140,7 +137,7 @@ describe('ArchiveManager', function() {
       it('should return the callback with an error', function() {
         return sinon.assert.calledWithExactly(
           this.callback,
-          new EmptyZipFileError()
+          sinon.match.instanceOf(ArchiveErrors.EmptyZipFileError)
         )
       })
     })
@@ -161,7 +158,7 @@ describe('ArchiveManager', function() {
       it('should return the callback with an error', function() {
         return sinon.assert.calledWithExactly(
           this.callback,
-          new EmptyZipFileError()
+          sinon.match.instanceOf(ArchiveErrors.EmptyZipFileError)
         )
       })
     })
@@ -170,7 +167,7 @@ describe('ArchiveManager', function() {
       beforeEach(function(done) {
         this.yauzl.open = sinon
           .stub()
-          .callsArgWith(2, new InvalidZipFileError())
+          .callsArgWith(2, new ArchiveErrors.InvalidZipFileError())
         return this.ArchiveManager.extractZipArchive(
           this.source,
           this.destination,
@@ -184,7 +181,7 @@ describe('ArchiveManager', function() {
       it('should return the callback with an error', function() {
         return sinon.assert.calledWithExactly(
           this.callback,
-          new InvalidZipFileError()
+          sinon.match.instanceOf(ArchiveErrors.InvalidZipFileError)
         )
       })
 
@@ -211,7 +208,7 @@ describe('ArchiveManager', function() {
       it('should return the callback with an error', function() {
         return sinon.assert.calledWithExactly(
           this.callback,
-          new ZipContentsTooLargeError()
+          sinon.match.instanceOf(ArchiveErrors.ZipContentsTooLargeError)
         )
       })
 
@@ -234,9 +231,11 @@ describe('ArchiveManager', function() {
       })
 
       it('should return the callback with an error', function() {
-        return this.callback
-          .calledWithExactly(new Error('Something went wrong'))
-          .should.equal(true)
+        return this.callback.should.have.been.calledWithExactly(
+          sinon.match
+            .instanceOf(Error)
+            .and(sinon.match.has('message', 'Something went wrong'))
+        )
       })
 
       it('should log out the error', function() {
@@ -380,9 +379,11 @@ describe('ArchiveManager', function() {
       })
 
       it('should return the callback with an error', function() {
-        return this.callback
-          .calledWithExactly(new Error('Something went wrong'))
-          .should.equal(true)
+        return this.callback.should.have.been.calledWithExactly(
+          sinon.match
+            .instanceOf(Error)
+            .and(sinon.match.has('message', 'Something went wrong'))
+        )
       })
 
       it('should log out the error', function() {
@@ -418,9 +419,11 @@ describe('ArchiveManager', function() {
       })
 
       it('should return the callback with an error', function() {
-        return this.callback
-          .calledWithExactly(new Error('Something went wrong'))
-          .should.equal(true)
+        return this.callback.should.have.been.calledWithExactly(
+          sinon.match
+            .instanceOf(Error)
+            .and(sinon.match.has('message', 'Something went wrong'))
+        )
       })
 
       it('should log out the error', function() {
@@ -458,9 +461,11 @@ describe('ArchiveManager', function() {
       })
 
       it('should return the callback with an error', function() {
-        return this.callback
-          .calledWithExactly(new Error('Something went wrong'))
-          .should.equal(true)
+        return this.callback.should.have.been.calledWithExactly(
+          sinon.match
+            .instanceOf(Error)
+            .and(sinon.match.has('message', 'Something went wrong'))
+        )
       })
 
       it('should log out the error', function() {

+ 1 - 1
services/web/test/unit/src/Uploads/ProjectUploadManagerTests.js

@@ -389,7 +389,7 @@ describe('ProjectUploadManager', function() {
   describe('_getDestinationDirectory', function() {
     it('should return the path with the time appended', function() {
       const date = Date.now()
-      sinon.stub(Date, 'now', () => date)
+      sinon.stub(Date, 'now').returns(date)
       this.ProjectUploadManager._getDestinationDirectory(
         '/path/to/zip/file.zip'
       ).should.equal(`/path/to/zip/file-${date}`)

+ 1 - 1
services/web/test/unit/src/User/UserDeleterTests.js

@@ -470,7 +470,7 @@ describe('UserDeleter', function() {
     describe('when called as a callback', function() {
       it('should expire the user', function(done) {
         this.UserDeleter.expireDeletedUser('giraffe', err => {
-          expect(err).not.to.exists
+          expect(err).not.to.exist
           this.DeletedUserMock.verify()
           this.mockedDeletedUser.verify()
           expect(this.deletedUser.user).not.to.exist

+ 2 - 1
services/web/test/unit/src/User/UserRegistrationHandlerTests.js

@@ -156,7 +156,8 @@ describe('UserRegistrationHandler', function() {
         return this.handler.registerNewUser(
           this.passingRequest,
           (err, user) => {
-            err.should.deep.equal(new Error('EmailAlreadyRegistered'))
+            expect(err).to.be.instanceOf(Error)
+            expect(err).to.have.property('message', 'EmailAlreadyRegistered')
             user.should.deep.equal(this.user)
             return done()
           }

+ 2 - 2
services/web/test/unit/src/UserMembership/UserMembershipControllerTests.js

@@ -179,7 +179,7 @@ describe('UserMembershipController', function() {
     it('handle readOnly entity', function(done) {
       this.req.entityConfig = EntityConfigs.group
       return this.UserMembershipController.add(this.req, null, error => {
-        expect(error).to.extist
+        expect(error).to.exist
         expect(error).to.be.an.instanceof(Errors.NotFoundError)
         return done()
       })
@@ -246,7 +246,7 @@ describe('UserMembershipController', function() {
     it('handle readOnly entity', function(done) {
       this.req.entityConfig = EntityConfigs.group
       return this.UserMembershipController.remove(this.req, null, error => {
-        expect(error).to.extist
+        expect(error).to.exist
         expect(error).to.be.an.instanceof(Errors.NotFoundError)
         return done()
       })

+ 3 - 1
services/web/test/unit/src/infrastructure/LockManager/getLockTests.js

@@ -120,7 +120,9 @@ describe('LockManager - getting the lock', function() {
     })
 
     it('should return the callback with an error', function() {
-      return this.callback.calledWith(new Error('timeout')).should.equal(true)
+      this.callback.should.have.been.calledWith(
+        sinon.match.instanceOf(Error).and(sinon.match.has('message', 'Timeout'))
+      )
     })
   })
 

+ 1 - 1
services/web/test/unit/src/infrastructure/ProxyManagerTests.js

@@ -21,7 +21,7 @@ const MockRequest = require('../helpers/MockRequest')
 const MockResponse = require('../helpers/MockResponse')
 
 describe('ProxyManager', function() {
-  before(function() {
+  beforeEach(function() {
     this.settings = { proxyUrls: {} }
     this.request = sinon.stub().returns({
       on() {},

Некоторые файлы не были показаны из-за большого количества измененных файлов