NotificationsTests.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /* eslint-disable
  2. camelcase,
  3. handle-callback-err,
  4. no-dupe-keys,
  5. no-return-assign,
  6. no-unused-vars,
  7. */
  8. // TODO: This file was created by bulk-decaffeinate.
  9. // Fix any style issues and re-enable lint.
  10. /*
  11. * decaffeinate suggestions:
  12. * DS102: Remove unnecessary code created because of implicit returns
  13. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  14. */
  15. const sinon = require('sinon')
  16. const chai = require('chai')
  17. const expect = chai.should
  18. const should = chai.should()
  19. const modulePath = '../../../app/js/Notifications.js'
  20. const SandboxedModule = require('sandboxed-module')
  21. const assert = require('assert')
  22. const { ObjectId } = require('mongodb')
  23. const user_id = '51dc93e6fb625a261300003b'
  24. const notification_id = 'fb625a26f09d'
  25. const notification_key = 'notification-key'
  26. describe('Notifications Tests', function () {
  27. beforeEach(function () {
  28. this.findToArrayStub = sinon.stub()
  29. this.findStub = sinon.stub().returns({ toArray: this.findToArrayStub })
  30. this.countStub = sinon.stub()
  31. this.updateOneStub = sinon.stub()
  32. this.deleteOneStub = sinon.stub()
  33. this.db = {
  34. notifications: {
  35. find: this.findStub,
  36. count: this.countStub,
  37. updateOne: this.updateOneStub,
  38. deleteOne: this.deleteOneStub
  39. }
  40. }
  41. this.notifications = SandboxedModule.require(modulePath, {
  42. requires: {
  43. 'logger-sharelatex': {
  44. log() {},
  45. error() {}
  46. },
  47. 'settings-sharelatex': {},
  48. './mongodb': { db: this.db, ObjectId },
  49. '@overleaf/metrics': { timeAsyncMethod: sinon.stub() }
  50. },
  51. globals: {
  52. console
  53. }
  54. })
  55. this.stubbedNotification = {
  56. user_id: ObjectId(user_id),
  57. key: 'notification-key',
  58. messageOpts: 'some info',
  59. templateKey: 'template-key'
  60. }
  61. return (this.stubbedNotificationArray = [this.stubbedNotification])
  62. })
  63. describe('getUserNotifications', function () {
  64. return it('should find all notifications and return i', function (done) {
  65. this.findToArrayStub.callsArgWith(0, null, this.stubbedNotificationArray)
  66. return this.notifications.getUserNotifications(
  67. user_id,
  68. (err, notifications) => {
  69. notifications.should.equal(this.stubbedNotificationArray)
  70. assert.deepEqual(this.findStub.args[0][0], {
  71. user_id: ObjectId(user_id),
  72. templateKey: { $exists: true }
  73. })
  74. return done()
  75. }
  76. )
  77. })
  78. })
  79. describe('addNotification', function () {
  80. beforeEach(function () {
  81. this.stubbedNotification = {
  82. user_id: ObjectId(user_id),
  83. key: 'notification-key',
  84. messageOpts: 'some info',
  85. templateKey: 'template-key'
  86. }
  87. this.expectedDocument = {
  88. user_id: this.stubbedNotification.user_id,
  89. key: 'notification-key',
  90. messageOpts: 'some info',
  91. templateKey: 'template-key'
  92. }
  93. this.expectedQuery = {
  94. user_id: this.stubbedNotification.user_id,
  95. key: 'notification-key'
  96. }
  97. this.updateOneStub.yields()
  98. return this.countStub.yields(null, 0)
  99. })
  100. it('should insert the notification into the collection', function (done) {
  101. return this.notifications.addNotification(
  102. user_id,
  103. this.stubbedNotification,
  104. (err) => {
  105. expect(err).not.exists
  106. sinon.assert.calledWith(
  107. this.updateOneStub,
  108. this.expectedQuery,
  109. { $set: this.expectedDocument },
  110. { upsert: true }
  111. )
  112. return done()
  113. }
  114. )
  115. })
  116. describe('when there is an existing notification', function (done) {
  117. beforeEach(function () {
  118. return this.countStub.yields(null, 1)
  119. })
  120. it('should fail to insert', function (done) {
  121. return this.notifications.addNotification(
  122. user_id,
  123. this.stubbedNotification,
  124. (err) => {
  125. expect(err).not.exists
  126. sinon.assert.notCalled(this.updateOneStub)
  127. return done()
  128. }
  129. )
  130. })
  131. return it('should update the key if forceCreate is true', function (done) {
  132. this.stubbedNotification.forceCreate = true
  133. return this.notifications.addNotification(
  134. user_id,
  135. this.stubbedNotification,
  136. (err) => {
  137. expect(err).not.exists
  138. sinon.assert.calledWith(
  139. this.updateOneStub,
  140. this.expectedQuery,
  141. { $set: this.expectedDocument },
  142. { upsert: true }
  143. )
  144. return done()
  145. }
  146. )
  147. })
  148. })
  149. describe('when the notification is set to expire', function () {
  150. beforeEach(function () {
  151. this.stubbedNotification = {
  152. user_id: ObjectId(user_id),
  153. key: 'notification-key',
  154. messageOpts: 'some info',
  155. templateKey: 'template-key',
  156. expires: '2922-02-13T09:32:56.289Z'
  157. }
  158. this.expectedDocument = {
  159. user_id: this.stubbedNotification.user_id,
  160. key: 'notification-key',
  161. messageOpts: 'some info',
  162. templateKey: 'template-key',
  163. expires: new Date(this.stubbedNotification.expires)
  164. }
  165. return (this.expectedQuery = {
  166. user_id: this.stubbedNotification.user_id,
  167. key: 'notification-key'
  168. })
  169. })
  170. return it('should add an `expires` Date field to the document', function (done) {
  171. return this.notifications.addNotification(
  172. user_id,
  173. this.stubbedNotification,
  174. (err) => {
  175. expect(err).not.exists
  176. sinon.assert.calledWith(
  177. this.updateOneStub,
  178. this.expectedQuery,
  179. { $set: this.expectedDocument },
  180. { upsert: true }
  181. )
  182. return done()
  183. }
  184. )
  185. })
  186. })
  187. return describe('when the notification has a nonsensical expires field', function () {
  188. beforeEach(function () {
  189. this.stubbedNotification = {
  190. user_id: ObjectId(user_id),
  191. key: 'notification-key',
  192. messageOpts: 'some info',
  193. templateKey: 'template-key',
  194. expires: 'WAT'
  195. }
  196. return (this.expectedDocument = {
  197. user_id: this.stubbedNotification.user_id,
  198. key: 'notification-key',
  199. messageOpts: 'some info',
  200. templateKey: 'template-key',
  201. expires: new Date(this.stubbedNotification.expires)
  202. })
  203. })
  204. return it('should produce an error', function (done) {
  205. return this.notifications.addNotification(
  206. user_id,
  207. this.stubbedNotification,
  208. (err) => {
  209. ;(err instanceof Error).should.equal(true)
  210. sinon.assert.notCalled(this.updateOneStub)
  211. return done()
  212. }
  213. )
  214. })
  215. })
  216. })
  217. describe('removeNotificationId', function () {
  218. return it('should mark the notification id as read', function (done) {
  219. this.updateOneStub.callsArgWith(2, null)
  220. return this.notifications.removeNotificationId(
  221. user_id,
  222. notification_id,
  223. (err) => {
  224. const searchOps = {
  225. user_id: ObjectId(user_id),
  226. _id: ObjectId(notification_id)
  227. }
  228. const updateOperation = {
  229. $unset: { templateKey: true, messageOpts: true }
  230. }
  231. assert.deepEqual(this.updateOneStub.args[0][0], searchOps)
  232. assert.deepEqual(this.updateOneStub.args[0][1], updateOperation)
  233. return done()
  234. }
  235. )
  236. })
  237. })
  238. describe('removeNotificationKey', function () {
  239. return it('should mark the notification key as read', function (done) {
  240. this.updateOneStub.callsArgWith(2, null)
  241. return this.notifications.removeNotificationKey(
  242. user_id,
  243. notification_key,
  244. (err) => {
  245. const searchOps = {
  246. user_id: ObjectId(user_id),
  247. key: notification_key
  248. }
  249. const updateOperation = {
  250. $unset: { templateKey: true }
  251. }
  252. assert.deepEqual(this.updateOneStub.args[0][0], searchOps)
  253. assert.deepEqual(this.updateOneStub.args[0][1], updateOperation)
  254. return done()
  255. }
  256. )
  257. })
  258. })
  259. describe('removeNotificationByKeyOnly', function () {
  260. return it('should mark the notification key as read', function (done) {
  261. this.updateOneStub.callsArgWith(2, null)
  262. return this.notifications.removeNotificationByKeyOnly(
  263. notification_key,
  264. (err) => {
  265. const searchOps = { key: notification_key }
  266. const updateOperation = { $unset: { templateKey: true } }
  267. assert.deepEqual(this.updateOneStub.args[0][0], searchOps)
  268. assert.deepEqual(this.updateOneStub.args[0][1], updateOperation)
  269. return done()
  270. }
  271. )
  272. })
  273. })
  274. return describe('deleteNotificationByKeyOnly', function () {
  275. return it('should completely remove the notification', function (done) {
  276. this.deleteOneStub.callsArgWith(1, null)
  277. return this.notifications.deleteNotificationByKeyOnly(
  278. notification_key,
  279. (err) => {
  280. const searchOps = { key: notification_key }
  281. assert.deepEqual(this.deleteOneStub.args[0][0], searchOps)
  282. return done()
  283. }
  284. )
  285. })
  286. })
  287. })