ChatControllerTests.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /* eslint-disable
  2. camelcase,
  3. handle-callback-err,
  4. max-len,
  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 should = require('chai').should()
  16. const SandboxedModule = require('sandboxed-module')
  17. const assert = require('assert')
  18. const path = require('path')
  19. const sinon = require('sinon')
  20. const modulePath = path.join(
  21. __dirname,
  22. '../../../../app/src/Features/Chat/ChatController'
  23. )
  24. const { expect } = require('chai')
  25. describe('ChatController', function() {
  26. beforeEach(function() {
  27. this.user_id = 'mock-user-id'
  28. this.settings = {}
  29. this.ChatApiHandler = {}
  30. this.EditorRealTimeController = { emitToRoom: sinon.stub() }
  31. this.AuthenticationController = {
  32. getLoggedInUserId: sinon.stub().returns(this.user_id)
  33. }
  34. this.ChatController = SandboxedModule.require(modulePath, {
  35. globals: {
  36. console: console
  37. },
  38. requires: {
  39. 'settings-sharelatex': this.settings,
  40. 'logger-sharelatex': {
  41. log() {}
  42. },
  43. './ChatApiHandler': this.ChatApiHandler,
  44. '../Editor/EditorRealTimeController': this.EditorRealTimeController,
  45. '../Authentication/AuthenticationController': this
  46. .AuthenticationController,
  47. '../User/UserInfoManager': (this.UserInfoManager = {}),
  48. '../User/UserInfoController': (this.UserInfoController = {}),
  49. '../Comments/CommentsController': (this.CommentsController = {})
  50. }
  51. })
  52. this.req = {
  53. params: {
  54. project_id: this.project_id
  55. }
  56. }
  57. return (this.res = {
  58. json: sinon.stub(),
  59. send: sinon.stub()
  60. })
  61. })
  62. describe('sendMessage', function() {
  63. beforeEach(function() {
  64. this.req.body = { content: (this.content = 'message-content') }
  65. this.UserInfoManager.getPersonalInfo = sinon
  66. .stub()
  67. .yields(null, (this.user = { unformatted: 'user' }))
  68. this.UserInfoController.formatPersonalInfo = sinon
  69. .stub()
  70. .returns((this.formatted_user = { formatted: 'user' }))
  71. this.ChatApiHandler.sendGlobalMessage = sinon
  72. .stub()
  73. .yields(
  74. null,
  75. (this.message = { mock: 'message', user_id: this.user_id })
  76. )
  77. return this.ChatController.sendMessage(this.req, this.res)
  78. })
  79. it('should look up the user', function() {
  80. return this.UserInfoManager.getPersonalInfo
  81. .calledWith(this.user_id)
  82. .should.equal(true)
  83. })
  84. it('should format and inject the user into the message', function() {
  85. this.UserInfoController.formatPersonalInfo
  86. .calledWith(this.user)
  87. .should.equal(true)
  88. return this.message.user.should.deep.equal(this.formatted_user)
  89. })
  90. it('should tell the chat handler about the message', function() {
  91. return this.ChatApiHandler.sendGlobalMessage
  92. .calledWith(this.project_id, this.user_id, this.content)
  93. .should.equal(true)
  94. })
  95. it('should tell the editor real time controller about the update with the data from the chat handler', function() {
  96. return this.EditorRealTimeController.emitToRoom
  97. .calledWith(this.project_id, 'new-chat-message', this.message)
  98. .should.equal(true)
  99. })
  100. it('should return a 204 status code', function() {
  101. return this.res.send.calledWith(204).should.equal(true)
  102. })
  103. })
  104. describe('getMessages', function() {
  105. beforeEach(function() {
  106. this.req.query = {
  107. limit: (this.limit = '30'),
  108. before: (this.before = '12345')
  109. }
  110. this.ChatController._injectUserInfoIntoThreads = sinon.stub().yields()
  111. this.ChatApiHandler.getGlobalMessages = sinon
  112. .stub()
  113. .yields(null, (this.messages = ['mock', 'messages']))
  114. return this.ChatController.getMessages(this.req, this.res)
  115. })
  116. it('should ask the chat handler about the request', function() {
  117. return this.ChatApiHandler.getGlobalMessages
  118. .calledWith(this.project_id, this.limit, this.before)
  119. .should.equal(true)
  120. })
  121. it('should return the messages', function() {
  122. return this.res.json.calledWith(this.messages).should.equal(true)
  123. })
  124. })
  125. describe('_injectUserInfoIntoThreads', function() {
  126. beforeEach(function() {
  127. this.users = {
  128. user_id_1: {
  129. mock: 'user_1'
  130. },
  131. user_id_2: {
  132. mock: 'user_2'
  133. }
  134. }
  135. this.UserInfoManager.getPersonalInfo = (user_id, callback) => {
  136. return callback(null, this.users[user_id])
  137. }
  138. sinon.spy(this.UserInfoManager, 'getPersonalInfo')
  139. return (this.UserInfoController.formatPersonalInfo = user => ({
  140. formatted: user['mock']
  141. }))
  142. })
  143. it('should inject a user object into messaged and resolved data', function(done) {
  144. return this.ChatController._injectUserInfoIntoThreads(
  145. {
  146. thread1: {
  147. resolved: true,
  148. resolved_by_user_id: 'user_id_1',
  149. messages: [
  150. {
  151. user_id: 'user_id_1',
  152. content: 'foo'
  153. },
  154. {
  155. user_id: 'user_id_2',
  156. content: 'bar'
  157. }
  158. ]
  159. },
  160. thread2: {
  161. messages: [
  162. {
  163. user_id: 'user_id_1',
  164. content: 'baz'
  165. }
  166. ]
  167. }
  168. },
  169. function(error, threads) {
  170. expect(threads).to.deep.equal({
  171. thread1: {
  172. resolved: true,
  173. resolved_by_user_id: 'user_id_1',
  174. resolved_by_user: { formatted: 'user_1' },
  175. messages: [
  176. {
  177. user_id: 'user_id_1',
  178. user: { formatted: 'user_1' },
  179. content: 'foo'
  180. },
  181. {
  182. user_id: 'user_id_2',
  183. user: { formatted: 'user_2' },
  184. content: 'bar'
  185. }
  186. ]
  187. },
  188. thread2: {
  189. messages: [
  190. {
  191. user_id: 'user_id_1',
  192. user: { formatted: 'user_1' },
  193. content: 'baz'
  194. }
  195. ]
  196. }
  197. })
  198. return done()
  199. }
  200. )
  201. })
  202. it('should only need to look up each user once', function(done) {
  203. return this.ChatController._injectUserInfoIntoThreads(
  204. [
  205. {
  206. messages: [
  207. {
  208. user_id: 'user_id_1',
  209. content: 'foo'
  210. },
  211. {
  212. user_id: 'user_id_1',
  213. content: 'bar'
  214. }
  215. ]
  216. }
  217. ],
  218. (error, threads) => {
  219. this.UserInfoManager.getPersonalInfo.calledOnce.should.equal(true)
  220. return done()
  221. }
  222. )
  223. })
  224. })
  225. })