CommentsControllerTests.coffee 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. should = require('chai').should()
  2. SandboxedModule = require('sandboxed-module')
  3. assert = require('assert')
  4. path = require('path')
  5. sinon = require('sinon')
  6. modulePath = path.join __dirname, "../../../../app/js/Features/Comments/CommentsController"
  7. expect = require("chai").expect
  8. describe "CommentsController", ->
  9. beforeEach ->
  10. @user_id = 'mock-user-id'
  11. @settings = {}
  12. @ChatApiHandler = {}
  13. @EditorRealTimeController =
  14. emitToRoom:sinon.stub()
  15. @AuthenticationController =
  16. getLoggedInUserId: sinon.stub().returns(@user_id)
  17. @CommentsController = SandboxedModule.require modulePath, requires:
  18. "settings-sharelatex": @settings
  19. "logger-sharelatex": log: ->
  20. "../Chat/ChatApiHandler": @ChatApiHandler
  21. "../Editor/EditorRealTimeController": @EditorRealTimeController
  22. '../Authentication/AuthenticationController': @AuthenticationController
  23. '../User/UserInfoManager': @UserInfoManager = {}
  24. '../User/UserInfoController': @UserInfoController = {}
  25. @req = {}
  26. @res =
  27. json: sinon.stub()
  28. send: sinon.stub()
  29. describe "sendComment", ->
  30. beforeEach ->
  31. @req.params =
  32. project_id: @project_id = "mock-project-id"
  33. thread_id: @thread_id = "mock-thread-id"
  34. @req.body =
  35. content: @content = "message-content"
  36. @UserInfoManager.getPersonalInfo = sinon.stub().yields(null, @user = {"unformatted": "user"})
  37. @UserInfoController.formatPersonalInfo = sinon.stub().returns(@formatted_user = {"formatted": "user"})
  38. @ChatApiHandler.sendComment = sinon.stub().yields(null, @message = {"mock": "message", user_id: @user_id})
  39. @CommentsController.sendComment @req, @res
  40. it "should look up the user", ->
  41. @UserInfoManager.getPersonalInfo
  42. .calledWith(@user_id)
  43. .should.equal true
  44. it "should format and inject the user into the comment", ->
  45. @UserInfoController.formatPersonalInfo
  46. .calledWith(@user)
  47. .should.equal true
  48. @message.user.should.deep.equal @formatted_user
  49. it "should tell the chat handler about the message", ->
  50. @ChatApiHandler.sendComment
  51. .calledWith(@project_id, @thread_id, @user_id, @content)
  52. .should.equal true
  53. it "should tell the editor real time controller about the update with the data from the chat handler", ->
  54. @EditorRealTimeController.emitToRoom
  55. .calledWith(@project_id, "new-comment", @thread_id, @message)
  56. .should.equal true
  57. it "should return a 204 status code", ->
  58. @res.send.calledWith(204).should.equal true
  59. describe "getThreads", ->
  60. beforeEach ->
  61. @req.params =
  62. project_id: @project_id = "mock-project-id"
  63. @ChatApiHandler.getThreads = sinon.stub().yields(null, @threads = {"mock", "threads"})
  64. @CommentsController._injectUserInfoIntoThreads = sinon.stub().yields(null, @threads)
  65. @CommentsController.getThreads @req, @res
  66. it "should ask the chat handler about the request", ->
  67. @ChatApiHandler.getThreads
  68. .calledWith(@project_id)
  69. .should.equal true
  70. it "should inject the user details into the threads", ->
  71. @CommentsController._injectUserInfoIntoThreads
  72. .calledWith(@threads)
  73. .should.equal true
  74. it "should return the messages", ->
  75. @res.json.calledWith(@threads).should.equal true
  76. describe "resolveThread", ->
  77. beforeEach ->
  78. @req.params =
  79. project_id: @project_id = "mock-project-id"
  80. thread_id: @thread_id = "mock-thread-id"
  81. @ChatApiHandler.resolveThread = sinon.stub().yields()
  82. @UserInfoManager.getPersonalInfo = sinon.stub().yields(null, @user = {"unformatted": "user"})
  83. @UserInfoController.formatPersonalInfo = sinon.stub().returns(@formatted_user = {"formatted": "user"})
  84. @CommentsController.resolveThread @req, @res
  85. it "should ask the chat handler to resolve the thread", ->
  86. @ChatApiHandler.resolveThread
  87. .calledWith(@project_id, @thread_id)
  88. .should.equal true
  89. it "should look up the user", ->
  90. @UserInfoManager.getPersonalInfo
  91. .calledWith(@user_id)
  92. .should.equal true
  93. it "should tell the client the comment was resolved", ->
  94. @EditorRealTimeController.emitToRoom
  95. .calledWith(@project_id, "resolve-thread", @thread_id, @formatted_user)
  96. .should.equal true
  97. it "should return a success code", ->
  98. @res.send.calledWith(204).should.equal
  99. describe "reopenThread", ->
  100. beforeEach ->
  101. @req.params =
  102. project_id: @project_id = "mock-project-id"
  103. thread_id: @thread_id = "mock-thread-id"
  104. @ChatApiHandler.reopenThread = sinon.stub().yields()
  105. @CommentsController.reopenThread @req, @res
  106. it "should ask the chat handler to reopen the thread", ->
  107. @ChatApiHandler.reopenThread
  108. .calledWith(@project_id, @thread_id)
  109. .should.equal true
  110. it "should tell the client the comment was resolved", ->
  111. @EditorRealTimeController.emitToRoom
  112. .calledWith(@project_id, "reopen-thread", @thread_id)
  113. .should.equal true
  114. it "should return a success code", ->
  115. @res.send.calledWith(204).should.equal
  116. describe "_injectUserInfoIntoThreads", ->
  117. beforeEach ->
  118. @users = {
  119. "user_id_1": {
  120. "mock": "user_1"
  121. }
  122. "user_id_2": {
  123. "mock": "user_2"
  124. }
  125. }
  126. @UserInfoManager.getPersonalInfo = (user_id, callback) =>
  127. return callback(null, @users[user_id])
  128. sinon.spy @UserInfoManager, "getPersonalInfo"
  129. @UserInfoController.formatPersonalInfo = (user) ->
  130. return { "formatted": user["mock"] }
  131. it "should inject a user object into messaged and resolved data", (done) ->
  132. @CommentsController._injectUserInfoIntoThreads {
  133. thread1: {
  134. resolved: true
  135. resolved_by_user_id: "user_id_1"
  136. messages: [{
  137. user_id: "user_id_1"
  138. content: "foo"
  139. }, {
  140. user_id: "user_id_2"
  141. content: "bar"
  142. }]
  143. },
  144. thread2: {
  145. messages: [{
  146. user_id: "user_id_1"
  147. content: "baz"
  148. }]
  149. }
  150. }, (error, threads) ->
  151. expect(threads).to.deep.equal {
  152. thread1: {
  153. resolved: true
  154. resolved_by_user_id: "user_id_1"
  155. resolved_by_user: { "formatted": "user_1" }
  156. messages: [{
  157. user_id: "user_id_1"
  158. user: { "formatted": "user_1" }
  159. content: "foo"
  160. }, {
  161. user_id: "user_id_2"
  162. user: { "formatted": "user_2" }
  163. content: "bar"
  164. }]
  165. },
  166. thread2: {
  167. messages: [{
  168. user_id: "user_id_1"
  169. user: { "formatted": "user_1" }
  170. content: "baz"
  171. }]
  172. }
  173. }
  174. done()
  175. it "should only need to look up each user once", (done) ->
  176. @CommentsController._injectUserInfoIntoThreads [{
  177. messages: [{
  178. user_id: "user_id_1"
  179. content: "foo"
  180. }, {
  181. user_id: "user_id_1"
  182. content: "bar"
  183. }]
  184. }], (error, threads) =>
  185. @UserInfoManager.getPersonalInfo.calledOnce.should.equal true
  186. done()