ChatControllerTests.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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. this.res = {
  58. json: sinon.stub(),
  59. send: sinon.stub(),
  60. sendStatus: sinon.stub()
  61. }
  62. })
  63. describe('sendMessage', function() {
  64. beforeEach(function() {
  65. this.req.body = { content: (this.content = 'message-content') }
  66. this.UserInfoManager.getPersonalInfo = sinon
  67. .stub()
  68. .yields(null, (this.user = { unformatted: 'user' }))
  69. this.UserInfoController.formatPersonalInfo = sinon
  70. .stub()
  71. .returns((this.formatted_user = { formatted: 'user' }))
  72. this.ChatApiHandler.sendGlobalMessage = sinon
  73. .stub()
  74. .yields(
  75. null,
  76. (this.message = { mock: 'message', user_id: this.user_id })
  77. )
  78. return this.ChatController.sendMessage(this.req, this.res)
  79. })
  80. it('should look up the user', function() {
  81. return this.UserInfoManager.getPersonalInfo
  82. .calledWith(this.user_id)
  83. .should.equal(true)
  84. })
  85. it('should format and inject the user into the message', function() {
  86. this.UserInfoController.formatPersonalInfo
  87. .calledWith(this.user)
  88. .should.equal(true)
  89. return this.message.user.should.deep.equal(this.formatted_user)
  90. })
  91. it('should tell the chat handler about the message', function() {
  92. return this.ChatApiHandler.sendGlobalMessage
  93. .calledWith(this.project_id, this.user_id, this.content)
  94. .should.equal(true)
  95. })
  96. it('should tell the editor real time controller about the update with the data from the chat handler', function() {
  97. return this.EditorRealTimeController.emitToRoom
  98. .calledWith(this.project_id, 'new-chat-message', this.message)
  99. .should.equal(true)
  100. })
  101. it('should return a 204 status code', function() {
  102. return this.res.sendStatus.calledWith(204).should.equal(true)
  103. })
  104. })
  105. describe('getMessages', function() {
  106. beforeEach(function() {
  107. this.req.query = {
  108. limit: (this.limit = '30'),
  109. before: (this.before = '12345')
  110. }
  111. this.ChatController._injectUserInfoIntoThreads = sinon.stub().yields()
  112. this.ChatApiHandler.getGlobalMessages = sinon
  113. .stub()
  114. .yields(null, (this.messages = ['mock', 'messages']))
  115. return this.ChatController.getMessages(this.req, this.res)
  116. })
  117. it('should ask the chat handler about the request', function() {
  118. return this.ChatApiHandler.getGlobalMessages
  119. .calledWith(this.project_id, this.limit, this.before)
  120. .should.equal(true)
  121. })
  122. it('should return the messages', function() {
  123. return this.res.json.calledWith(this.messages).should.equal(true)
  124. })
  125. })
  126. describe('_injectUserInfoIntoThreads', function() {
  127. beforeEach(function() {
  128. this.users = {
  129. user_id_1: {
  130. mock: 'user_1'
  131. },
  132. user_id_2: {
  133. mock: 'user_2'
  134. }
  135. }
  136. this.UserInfoManager.getPersonalInfo = (user_id, callback) => {
  137. return callback(null, this.users[user_id])
  138. }
  139. sinon.spy(this.UserInfoManager, 'getPersonalInfo')
  140. return (this.UserInfoController.formatPersonalInfo = user => ({
  141. formatted: user['mock']
  142. }))
  143. })
  144. it('should inject a user object into messaged and resolved data', function(done) {
  145. return this.ChatController._injectUserInfoIntoThreads(
  146. {
  147. thread1: {
  148. resolved: true,
  149. resolved_by_user_id: 'user_id_1',
  150. messages: [
  151. {
  152. user_id: 'user_id_1',
  153. content: 'foo'
  154. },
  155. {
  156. user_id: 'user_id_2',
  157. content: 'bar'
  158. }
  159. ]
  160. },
  161. thread2: {
  162. messages: [
  163. {
  164. user_id: 'user_id_1',
  165. content: 'baz'
  166. }
  167. ]
  168. }
  169. },
  170. (error, threads) => {
  171. expect(threads).to.deep.equal({
  172. thread1: {
  173. resolved: true,
  174. resolved_by_user_id: 'user_id_1',
  175. resolved_by_user: { formatted: 'user_1' },
  176. messages: [
  177. {
  178. user_id: 'user_id_1',
  179. user: { formatted: 'user_1' },
  180. content: 'foo'
  181. },
  182. {
  183. user_id: 'user_id_2',
  184. user: { formatted: 'user_2' },
  185. content: 'bar'
  186. }
  187. ]
  188. },
  189. thread2: {
  190. messages: [
  191. {
  192. user_id: 'user_id_1',
  193. user: { formatted: 'user_1' },
  194. content: 'baz'
  195. }
  196. ]
  197. }
  198. })
  199. return done()
  200. }
  201. )
  202. })
  203. it('should only need to look up each user once', function(done) {
  204. return this.ChatController._injectUserInfoIntoThreads(
  205. [
  206. {
  207. messages: [
  208. {
  209. user_id: 'user_id_1',
  210. content: 'foo'
  211. },
  212. {
  213. user_id: 'user_id_1',
  214. content: 'bar'
  215. }
  216. ]
  217. }
  218. ],
  219. (error, threads) => {
  220. this.UserInfoManager.getPersonalInfo.calledOnce.should.equal(true)
  221. return done()
  222. }
  223. )
  224. })
  225. })
  226. })