Sfoglia il codice sorgente

Switch to using vitest for tests

GitOrigin-RevId: 0e448010848011883f8843b6d3280e767cea932e
Andrew Rumble 1 anno fa
parent
commit
0a845b3f06

File diff suppressed because it is too large
+ 702 - 192
package-lock.json


+ 1 - 0
services/notifications/docker-compose.ci.yml

@@ -8,6 +8,7 @@ services:
     user: node
     volumes:
       - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it
+      - ../../tsconfig.backend.json:/overleaf/tsconfig.backend.json
     entrypoint: /overleaf/bin/shared/wait_for_it mongo:27017 --timeout=60 --
     command: npm run test:unit:_run
     environment:

+ 1 - 1
services/notifications/docker-compose.yml

@@ -9,6 +9,7 @@ services:
       - .:/overleaf/services/notifications
       - ../../node_modules:/overleaf/node_modules
       - ../../libraries:/overleaf/libraries
+      - ../../tsconfig.backend.json:/overleaf/tsconfig.backend.json
       - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it
     working_dir: /overleaf/services/notifications
     environment:
@@ -61,4 +62,3 @@ services:
       # replica set. This override is not needed when running the setup after
       # starting up mongo.
       - mongo:127.0.0.1
-

+ 6 - 8
services/notifications/package.json

@@ -8,9 +8,8 @@
     "start": "node app.js",
     "test:acceptance:_run": "mocha --recursive --reporter spec --timeout 15000 --exit $@ test/acceptance/js",
     "test:acceptance": "npm run test:acceptance:_run -- --grep=$MOCHA_GREP",
-    "test:unit:_run": "mocha --recursive --reporter spec --exit $@ test/unit/js",
-    "test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP",
-    "nodemon": "node --watch app.js",
+    "test:unit:_run": "vitest ${NO_CACHE:+\"--no-cache\"} $@ test/unit/js",
+    "test:unit": "npm run test:unit:_run",
     "lint": "eslint --max-warnings 0 --format unix .",
     "format": "prettier --list-different $PWD/'**/*.*js'",
     "format:fix": "prettier --write $PWD/'**/*.*js'",
@@ -24,6 +23,7 @@
     "@overleaf/metrics": "*",
     "@overleaf/mongo-utils": "*",
     "@overleaf/settings": "*",
+    "@overleaf/promise-utils": "*",
     "async": "^3.2.5",
     "body-parser": "^1.20.3",
     "bunyan": "^1.8.15",
@@ -33,11 +33,9 @@
     "request": "^2.88.2"
   },
   "devDependencies": {
-    "chai": "^4.3.6",
+    "@types/request": "^2.48.12",
     "chai-as-promised": "^7.1.1",
-    "mocha": "^11.1.0",
-    "sandboxed-module": "^2.0.4",
-    "sinon": "^9.2.4",
-    "typescript": "^5.0.4"
+    "typescript": "^5.0.4",
+    "vitest": "^3.2.4"
   }
 }

+ 19 - 22
services/notifications/test/setup.js

@@ -1,30 +1,27 @@
-const chai = require('chai')
-const SandboxedModule = require('sandboxed-module')
+import { afterEach, chai, vi } from 'vitest'
+import mongodb from 'mongodb-legacy'
+import chaiAsPromised from 'chai-as-promised'
 
 // Chai configuration
 chai.should()
+chai.use(chaiAsPromised)
 
 // ensure every ObjectId has the id string as a property for correct comparisons
-require('mongodb-legacy').ObjectId.cacheHexString = true
+mongodb.ObjectId.cacheHexString = true
 
-// SandboxedModule configuration
-SandboxedModule.configure({
-  requires: {
-    '@overleaf/logger': {
-      debug() {},
-      log() {},
-      info() {},
-      warn() {},
-      err() {},
-      error() {},
-      fatal() {},
-    },
-    'mongodb-legacy': require('mongodb-legacy'), // for ObjectId comparisons
-  },
-  globals: { Buffer, JSON, console, process },
-  sourceTransformers: {
-    removeNodePrefix: function (source) {
-      return source.replace(/require\(['"]node:/g, "require('")
-    },
+vi.mock('@overleaf/logger', () => ({
+  default: {
+    debug: vi.fn(),
+    log: vi.fn(),
+    info: vi.fn(),
+    warn: vi.fn(),
+    err: vi.fn(),
+    error: vi.fn(),
+    fatal: vi.fn(),
   },
+}))
+
+afterEach(() => {
+  vi.restoreAllMocks()
+  vi.resetModules()
 })

+ 146 - 209
services/notifications/test/unit/js/Notifications.test.js

@@ -1,302 +1,239 @@
-/* eslint-disable
-    no-dupe-keys,
-    no-return-assign,
-    no-unused-vars,
-*/
-// TODO: This file was created by bulk-decaffeinate.
-// Fix any style issues and re-enable lint.
-/*
- * decaffeinate suggestions:
- * DS102: Remove unnecessary code created because of implicit returns
- * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
- */
-import { stub, assert as _assert } from 'sinon'
-import { expect } from 'chai'
-import { require as _require } from 'sandboxed-module'
-import { deepEqual } from 'node:assert'
+import { beforeEach, describe, expect, it, vi } from 'vitest'
 import { ObjectId } from 'mongodb-legacy'
-
+import assert from 'node:assert'
 const modulePath = '../../../app/js/Notifications.js'
+
 const userId = '51dc93e6fb625a261300003b'
 const notificationId = '574ee8d6f40c3a244e704249'
 const notificationKey = 'notification-key'
 
-describe('Notifications Tests', function () {
-  beforeEach(function () {
-    this.findToArrayStub = stub()
-    this.findStub = stub().returns({ toArray: this.findToArrayStub })
-    this.countStub = stub()
-    this.updateOneStub = stub()
-    this.deleteOneStub = stub()
-    this.db = {
+describe('Notifications Tests', () => {
+  let countStub,
+    db,
+    deleteOneStub,
+    findStub,
+    findToArrayStub,
+    notifications,
+    stubbedNotification,
+    stubbedNotificationArray,
+    updateOneStub
+  beforeEach(async () => {
+    findToArrayStub = vi.fn()
+    findStub = vi.fn().mockReturnValue({ toArray: findToArrayStub })
+    countStub = vi.fn()
+    updateOneStub = vi.fn()
+    deleteOneStub = vi.fn()
+    db = {
       notifications: {
-        find: this.findStub,
-        count: this.countStub,
-        updateOne: this.updateOneStub,
-        deleteOne: this.deleteOneStub,
+        find: findStub,
+        count: countStub,
+        updateOne: updateOneStub,
+        deleteOne: deleteOneStub,
       },
     }
 
-    this.notifications = _require(modulePath, {
-      requires: {
-        '@overleaf/settings': {},
-        './mongodb': { db: this.db, ObjectId },
-      },
-    })
+    vi.doMock('@overleaf/settings', () => ({}))
+    vi.doMock('../../../app/js/mongodb', () => ({
+      db,
+      ObjectId,
+    }))
+
+    notifications = await import(modulePath)
 
-    this.stubbedNotification = {
+    stubbedNotification = {
       user_id: new ObjectId(userId),
       key: 'notification-key',
       messageOpts: 'some info',
       templateKey: 'template-key',
     }
-    return (this.stubbedNotificationArray = [this.stubbedNotification])
+    stubbedNotificationArray = [stubbedNotification]
   })
 
-  describe('getUserNotifications', function () {
-    return it('should find all notifications and return i', function (done) {
-      this.findToArrayStub.callsArgWith(0, null, this.stubbedNotificationArray)
-      return this.notifications.getUserNotifications(
-        userId,
-        (err, notifications) => {
-          if (err) return done(err)
-          notifications.should.equal(this.stubbedNotificationArray)
-          deepEqual(this.findStub.args[0][0], {
-            user_id: new ObjectId(userId),
-            templateKey: { $exists: true },
-          })
-          return done()
-        }
-      )
+  describe('getUserNotifications', () => {
+    it('should find all notifications and return i', async () => {
+      findToArrayStub.mockResolvedValue(stubbedNotificationArray)
+      const result = await notifications.getUserNotifications(userId)
+
+      result.should.equal(stubbedNotificationArray)
+      assert.deepEqual(findStub.mock.calls[0][0], {
+        user_id: new ObjectId(userId),
+        templateKey: { $exists: true },
+      })
     })
   })
 
-  describe('addNotification', function () {
-    beforeEach(function () {
-      this.stubbedNotification = {
+  describe('addNotification', () => {
+    let expectedDocument, expectedQuery
+    beforeEach(() => {
+      stubbedNotification = {
         user_id: new ObjectId(userId),
         key: 'notification-key',
         messageOpts: 'some info',
         templateKey: 'template-key',
       }
-      this.expectedDocument = {
-        user_id: this.stubbedNotification.user_id,
+      expectedDocument = {
+        user_id: stubbedNotification.user_id,
         key: 'notification-key',
         messageOpts: 'some info',
         templateKey: 'template-key',
       }
-      this.expectedQuery = {
-        user_id: this.stubbedNotification.user_id,
+      expectedQuery = {
+        user_id: stubbedNotification.user_id,
         key: 'notification-key',
       }
-      this.updateOneStub.yields()
-      return this.countStub.yields(null, 0)
+      updateOneStub.mockResolvedValue()
+      countStub.mockResolvedValue(0)
     })
 
-    it('should insert the notification into the collection', function (done) {
-      return this.notifications.addNotification(
-        userId,
-        this.stubbedNotification,
-        err => {
-          expect(err).not.to.exist
-          _assert.calledWith(
-            this.updateOneStub,
-            this.expectedQuery,
-            { $set: this.expectedDocument },
-            { upsert: true }
-          )
-          return done()
-        }
+    it('should insert the notification into the collection', async () => {
+      await notifications.addNotification(userId, stubbedNotification)
+
+      expect(updateOneStub).toHaveBeenCalledWith(
+        expectedQuery,
+        { $set: expectedDocument },
+        { upsert: true }
       )
     })
 
-    describe('when there is an existing notification', function (done) {
-      beforeEach(function () {
-        return this.countStub.yields(null, 1)
+    describe('when there is an existing notification', done => {
+      beforeEach(() => {
+        countStub.mockResolvedValue(1)
       })
 
-      it('should fail to insert', function (done) {
-        return this.notifications.addNotification(
-          userId,
-          this.stubbedNotification,
-          err => {
-            expect(err).not.to.exist
-            _assert.notCalled(this.updateOneStub)
-            return done()
-          }
-        )
+      it('should fail to insert', async () => {
+        await notifications.addNotification(userId, stubbedNotification)
+
+        expect(updateOneStub).not.toHaveBeenCalled()
       })
 
-      return it('should update the key if forceCreate is true', function (done) {
-        this.stubbedNotification.forceCreate = true
-        return this.notifications.addNotification(
-          userId,
-          this.stubbedNotification,
-          err => {
-            expect(err).not.to.exist
-            _assert.calledWith(
-              this.updateOneStub,
-              this.expectedQuery,
-              { $set: this.expectedDocument },
-              { upsert: true }
-            )
-            return done()
-          }
+      it('should update the key if forceCreate is true', async () => {
+        stubbedNotification.forceCreate = true
+        await notifications.addNotification(userId, stubbedNotification)
+
+        expect(updateOneStub).toHaveBeenCalledWith(
+          expectedQuery,
+          { $set: expectedDocument },
+          { upsert: true }
         )
       })
     })
 
-    describe('when the notification is set to expire', function () {
-      beforeEach(function () {
-        this.stubbedNotification = {
+    describe('when the notification is set to expire', () => {
+      beforeEach(() => {
+        stubbedNotification = {
           user_id: new ObjectId(userId),
           key: 'notification-key',
           messageOpts: 'some info',
           templateKey: 'template-key',
           expires: '2922-02-13T09:32:56.289Z',
         }
-        this.expectedDocument = {
-          user_id: this.stubbedNotification.user_id,
+        expectedDocument = {
+          user_id: stubbedNotification.user_id,
           key: 'notification-key',
           messageOpts: 'some info',
           templateKey: 'template-key',
-          expires: new Date(this.stubbedNotification.expires),
+          expires: new Date(stubbedNotification.expires),
         }
-        return (this.expectedQuery = {
-          user_id: this.stubbedNotification.user_id,
+        expectedQuery = {
+          user_id: stubbedNotification.user_id,
           key: 'notification-key',
-        })
+        }
       })
 
-      return it('should add an `expires` Date field to the document', function (done) {
-        return this.notifications.addNotification(
-          userId,
-          this.stubbedNotification,
-          err => {
-            expect(err).not.to.exist
-            _assert.calledWith(
-              this.updateOneStub,
-              this.expectedQuery,
-              { $set: this.expectedDocument },
-              { upsert: true }
-            )
-            return done()
-          }
+      it('should add an `expires` Date field to the document', async () => {
+        await notifications.addNotification(userId, stubbedNotification)
+
+        expect(updateOneStub).toHaveBeenCalledWith(
+          expectedQuery,
+          { $set: expectedDocument },
+          { upsert: true }
         )
       })
     })
 
-    return describe('when the notification has a nonsensical expires field', function () {
-      beforeEach(function () {
-        this.stubbedNotification = {
+    describe('when the notification has a nonsensical expires field', () => {
+      beforeEach(() => {
+        stubbedNotification = {
           user_id: new ObjectId(userId),
           key: 'notification-key',
           messageOpts: 'some info',
           templateKey: 'template-key',
           expires: 'WAT',
         }
-        return (this.expectedDocument = {
-          user_id: this.stubbedNotification.user_id,
+        expectedDocument = {
+          user_id: stubbedNotification.user_id,
           key: 'notification-key',
           messageOpts: 'some info',
           templateKey: 'template-key',
-          expires: new Date(this.stubbedNotification.expires),
-        })
+          expires: new Date(stubbedNotification.expires),
+        }
       })
 
-      return it('should produce an error', function (done) {
-        return this.notifications.addNotification(
-          userId,
-          this.stubbedNotification,
-          err => {
-            ;(err instanceof Error).should.equal(true)
-            _assert.notCalled(this.updateOneStub)
-            return done()
-          }
-        )
+      it('should produce an error', async () => {
+        await expect(
+          notifications.addNotification(userId, stubbedNotification)
+        ).to.eventually.be.rejectedWith(Error)
+
+        expect(updateOneStub).not.toHaveBeenCalled()
       })
     })
   })
 
-  describe('removeNotificationId', function () {
-    return it('should mark the notification id as read', function (done) {
-      this.updateOneStub.callsArgWith(2, null)
+  describe('removeNotificationId', () => {
+    it('should mark the notification id as read', async () => {
+      updateOneStub.mockResolvedValue(null)
 
-      return this.notifications.removeNotificationId(
-        userId,
-        notificationId,
-        err => {
-          if (err) return done(err)
-          const searchOps = {
-            user_id: new ObjectId(userId),
-            _id: new ObjectId(notificationId),
-          }
-          const updateOperation = {
-            $unset: { templateKey: true, messageOpts: true },
-          }
-          deepEqual(this.updateOneStub.args[0][0], searchOps)
-          deepEqual(this.updateOneStub.args[0][1], updateOperation)
-          return done()
-        }
-      )
+      await notifications.removeNotificationId(userId, notificationId)
+
+      const searchOps = {
+        user_id: new ObjectId(userId),
+        _id: new ObjectId(notificationId),
+      }
+      const updateOperation = {
+        $unset: { templateKey: true, messageOpts: true },
+      }
+      assert.deepEqual(updateOneStub.mock.calls[0][0], searchOps)
+      assert.deepEqual(updateOneStub.mock.calls[0][1], updateOperation)
     })
   })
 
-  describe('removeNotificationKey', function () {
-    return it('should mark the notification key as read', function (done) {
-      this.updateOneStub.callsArgWith(2, null)
+  describe('removeNotificationKey', () => {
+    it('should mark the notification key as read', async () => {
+      updateOneStub.mockResolvedValue(null)
 
-      return this.notifications.removeNotificationKey(
-        userId,
-        notificationKey,
-        err => {
-          if (err) return done(err)
-          const searchOps = {
-            user_id: new ObjectId(userId),
-            key: notificationKey,
-          }
-          const updateOperation = {
-            $unset: { templateKey: true },
-          }
-          deepEqual(this.updateOneStub.args[0][0], searchOps)
-          deepEqual(this.updateOneStub.args[0][1], updateOperation)
-          return done()
-        }
-      )
+      await notifications.removeNotificationKey(userId, notificationKey)
+      const searchOps = {
+        user_id: new ObjectId(userId),
+        key: notificationKey,
+      }
+      const updateOperation = {
+        $unset: { templateKey: true },
+      }
+      assert.deepEqual(updateOneStub.mock.calls[0][0], searchOps)
+      assert.deepEqual(updateOneStub.mock.calls[0][1], updateOperation)
     })
   })
 
-  describe('removeNotificationByKeyOnly', function () {
-    return it('should mark the notification key as read', function (done) {
-      this.updateOneStub.callsArgWith(2, null)
+  describe('removeNotificationByKeyOnly', () => {
+    it('should mark the notification key as read', async () => {
+      updateOneStub.mockResolvedValue(null)
 
-      return this.notifications.removeNotificationByKeyOnly(
-        notificationKey,
-        err => {
-          if (err) return done(err)
-          const searchOps = { key: notificationKey }
-          const updateOperation = { $unset: { templateKey: true } }
-          deepEqual(this.updateOneStub.args[0][0], searchOps)
-          deepEqual(this.updateOneStub.args[0][1], updateOperation)
-          return done()
-        }
-      )
+      await notifications.removeNotificationByKeyOnly(notificationKey)
+      const searchOps = { key: notificationKey }
+      const updateOperation = { $unset: { templateKey: true } }
+      assert.deepEqual(updateOneStub.mock.calls[0][0], searchOps)
+      assert.deepEqual(updateOneStub.mock.calls[0][1], updateOperation)
     })
   })
 
-  return describe('deleteNotificationByKeyOnly', function () {
-    return it('should completely remove the notification', function (done) {
-      this.deleteOneStub.callsArgWith(1, null)
+  describe('deleteNotificationByKeyOnly', () => {
+    it('should completely remove the notification', async () => {
+      deleteOneStub.mockResolvedValue()
 
-      return this.notifications.deleteNotificationByKeyOnly(
-        notificationKey,
-        err => {
-          if (err) return done(err)
-          const searchOps = { key: notificationKey }
-          deepEqual(this.deleteOneStub.args[0][0], searchOps)
-          return done()
-        }
-      )
+      await notifications.deleteNotificationByKeyOnly(notificationKey)
+
+      const searchOps = { key: notificationKey }
+      expect(deleteOneStub.mock.calls[0][0]).toEqual(searchOps)
     })
   })
 })

+ 94 - 82
services/notifications/test/unit/js/NotificationsController.test.js

@@ -1,7 +1,3 @@
-/* eslint-disable
-    no-return-assign,
-    no-unused-vars,
-*/
 // TODO: This file was created by bulk-decaffeinate.
 // Fix any style issues and re-enable lint.
 /*
@@ -9,141 +5,157 @@
  * DS102: Remove unnecessary code created because of implicit returns
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  */
-import { stub } from 'sinon'
-import { require as _require } from 'sandboxed-module'
-import assert from 'node:assert'
-
+import { beforeEach, describe, expect, it, vi } from 'vitest'
 const modulePath = '../../../app/js/NotificationsController.js'
+
 const userId = '51dc93e6fb625a261300003b'
 const notificationId = 'fb625a26f09d'
 const notificationKey = 'my-notification-key'
 
-describe('Notifications Controller', function () {
-  beforeEach(function () {
-    const self = this
-    this.notifications = {}
-    this.controller = _require(modulePath, {
-      requires: {
-        './Notifications': this.notifications,
-        '@overleaf/metrics': {
-          inc: stub(),
-        },
+describe('Notifications Controller', () => {
+  let controller, notifications, stubbedNotification
+  beforeEach(async () => {
+    notifications = {
+      addNotification: vi.fn(),
+      getUserNotifications: vi.fn(),
+      removeNotificationByKeyOnly: vi.fn(),
+      removeNotificationId: vi.fn(),
+      removeNotificationKey: vi.fn(),
+    }
+
+    vi.doMock('../../../app/js/Notifications', () => notifications)
+
+    vi.doMock('@overleaf/metrics', () => ({
+      default: {
+        inc: vi.fn(),
       },
-    })
+    }))
 
-    return (this.stubbedNotification = [
+    controller = (await import(modulePath)).default
+
+    stubbedNotification = [
       {
         key: notificationKey,
         messageOpts: 'some info',
         templateKey: 'template-key',
       },
-    ])
+    ]
   })
 
-  describe('getUserNotifications', function () {
-    return it('should ask the notifications for the users notifications', function (done) {
-      this.notifications.getUserNotifications = stub().callsArgWith(
-        1,
-        null,
-        this.stubbedNotification
-      )
+  describe('getUserNotifications', () => {
+    it('should ask the notifications for the users notifications', async () => {
+      notifications.getUserNotifications.mockResolvedValue(stubbedNotification)
       const req = {
         params: {
           user_id: userId,
         },
       }
-      return this.controller.getUserNotifications(req, {
-        json: result => {
-          result.should.equal(this.stubbedNotification)
-          this.notifications.getUserNotifications
-            .calledWith(userId)
-            .should.equal(true)
-          return done()
-        },
+      await new Promise(resolve => {
+        controller.getUserNotifications(req, {
+          json: result => {
+            expect(result).toBe(stubbedNotification)
+            expect(notifications.getUserNotifications).toHaveBeenCalledWith(
+              userId
+            )
+            resolve()
+          },
+        })
       })
     })
   })
 
-  describe('addNotification', function () {
-    return it('should tell the notifications to add the notification for the user', function (done) {
-      this.notifications.addNotification = stub().callsArgWith(2)
+  describe('addNotification', () => {
+    it('should tell the notifications to add the notification for the user', async () => {
+      notifications.addNotification.mockResolvedValue()
       const req = {
         params: {
           user_id: userId,
         },
-        body: this.stubbedNotification,
+        body: stubbedNotification,
       }
-      return this.controller.addNotification(req, {
-        sendStatus: code => {
-          this.notifications.addNotification
-            .calledWith(userId, this.stubbedNotification)
-            .should.equal(true)
-          code.should.equal(200)
-          return done()
-        },
+      await new Promise(resolve => {
+        controller.addNotification(req, {
+          sendStatus: code => {
+            expect(notifications.addNotification).toHaveBeenCalledWith(
+              userId,
+              stubbedNotification
+            )
+            expect(code).toBe(200)
+            resolve()
+          },
+        })
       })
     })
   })
 
-  describe('removeNotificationId', function () {
-    return it('should tell the notifications to mark the notification Id as read', function (done) {
-      this.notifications.removeNotificationId = stub().callsArgWith(2)
+  describe('removeNotificationId', () => {
+    it('should tell the notifications to mark the notification Id as read', async () => {
+      notifications.removeNotificationId.mockResolvedValue()
       const req = {
         params: {
           user_id: userId,
           notification_id: notificationId,
         },
       }
-      return this.controller.removeNotificationId(req, {
-        sendStatus: code => {
-          this.notifications.removeNotificationId
-            .calledWith(userId, notificationId)
-            .should.equal(true)
-          code.should.equal(200)
-          return done()
-        },
+      await new Promise(resolve => {
+        controller.removeNotificationId(req, {
+          sendStatus: code => {
+            expect(notifications.removeNotificationId).toHaveBeenCalledWith(
+              userId,
+              notificationId
+            )
+            expect(code).toBe(200)
+            resolve()
+          },
+        })
       })
     })
   })
 
-  describe('removeNotificationKey', function () {
-    return it('should tell the notifications to mark the notification Key as read', function (done) {
-      this.notifications.removeNotificationKey = stub().callsArgWith(2)
+  describe('removeNotificationKey', () => {
+    it('should tell the notifications to mark the notification Key as read', async () => {
+      notifications.removeNotificationKey.mockResolvedValue()
       const req = {
         params: {
           user_id: userId,
         },
         body: { key: notificationKey },
       }
-      return this.controller.removeNotificationKey(req, {
-        sendStatus: code => {
-          this.notifications.removeNotificationKey
-            .calledWith(userId, notificationKey)
-            .should.equal(true)
-          code.should.equal(200)
-          return done()
-        },
+      await new Promise(resolve => {
+        controller.removeNotificationKey(req, {
+          sendStatus: code => {
+            expect(notifications.removeNotificationKey).toHaveBeenCalledWith(
+              userId,
+              notificationKey
+            )
+            expect(code).toBe(200)
+            resolve()
+          },
+        })
       })
     })
   })
 
-  return describe('removeNotificationByKeyOnly', function () {
-    return it('should tell the notifications to mark the notification Key as read', function (done) {
-      this.notifications.removeNotificationByKeyOnly = stub().callsArgWith(1)
+  describe('removeNotificationByKeyOnly', () => {
+    it('should tell the notifications to mark the notification Key as read', async () => {
+      notifications.removeNotificationByKeyOnly.mockResolvedValue()
       const req = {
         params: {
           key: notificationKey,
         },
       }
-      return this.controller.removeNotificationByKeyOnly(req, {
-        sendStatus: code => {
-          this.notifications.removeNotificationByKeyOnly
-            .calledWith(notificationKey)
-            .should.equal(true)
-          code.should.equal(200)
-          return done()
-        },
-      })
+      await new Promise(resolve =>
+        controller.removeNotificationByKeyOnly(req, {
+          sendStatus: code => {
+            expect(
+              notifications.removeNotificationByKeyOnly
+            ).toHaveBeenCalledWith(notificationKey)
+
+            expect(code).toBe(200)
+            resolve()
+          },
+        })
+      )
     })
   })
 })

+ 1 - 0
services/notifications/tsconfig.json

@@ -2,6 +2,7 @@
   "extends": "../../tsconfig.backend.json",
   "include": [
     "app.js",
+    "vitest.config.cjs",
     "app/js/**/*",
     "benchmarks/**/*",
     "config/**/*",

Some files were not shown because too many files changed in this diff