ChatController.test.mjs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import { vi } from 'vitest'
  2. import sinon from 'sinon'
  3. const MODULE_PATH = '../../../../app/src/Features/Chat/ChatController.mjs'
  4. describe('ChatController', function () {
  5. beforeEach(async function (ctx) {
  6. ctx.user_id = 'mock-user-id'
  7. ctx.settings = {}
  8. ctx.ChatApiHandler = { promises: {} }
  9. ctx.ChatManager = { promises: {} }
  10. ctx.EditorRealTimeController = { emitToRoom: sinon.stub() }
  11. ctx.SessionManager = {
  12. getLoggedInUserId: sinon.stub().returns(ctx.user_id),
  13. }
  14. ctx.UserInfoManager = {
  15. promises: {},
  16. }
  17. ctx.UserInfoController = {}
  18. ctx.Modules = {
  19. promises: {
  20. hooks: {
  21. fire: sinon.stub().resolves(),
  22. },
  23. },
  24. }
  25. vi.doMock('@overleaf/settings', () => ({
  26. default: ctx.settings,
  27. }))
  28. vi.doMock('../../../../app/src/Features/Chat/ChatApiHandler.mjs', () => ({
  29. default: ctx.ChatApiHandler,
  30. }))
  31. vi.doMock('../../../../app/src/Features/Chat/ChatManager.mjs', () => ({
  32. default: ctx.ChatManager,
  33. }))
  34. vi.doMock(
  35. '../../../../app/src/Features/Editor/EditorRealTimeController.mjs',
  36. () => ({
  37. default: ctx.EditorRealTimeController,
  38. })
  39. )
  40. vi.doMock(
  41. '../../../../app/src/Features/Authentication/SessionManager.mjs',
  42. () => ({
  43. default: ctx.SessionManager,
  44. })
  45. )
  46. vi.doMock('../../../../app/src/Features/User/UserInfoManager.mjs', () => ({
  47. default: ctx.UserInfoManager,
  48. }))
  49. vi.doMock(
  50. '../../../../app/src/Features/User/UserInfoController.mjs',
  51. () => ({
  52. default: ctx.UserInfoController,
  53. })
  54. )
  55. vi.doMock('../../../../app/src/infrastructure/Modules.mjs', () => ({
  56. default: ctx.Modules,
  57. }))
  58. ctx.ChatController = (await import(MODULE_PATH)).default
  59. ctx.req = {
  60. params: {
  61. project_id: ctx.project_id,
  62. },
  63. }
  64. ctx.res = {
  65. json: sinon.stub(),
  66. send: sinon.stub(),
  67. sendStatus: sinon.stub(),
  68. }
  69. })
  70. describe('sendMessage', function () {
  71. beforeEach(async function (ctx) {
  72. ctx.req.body = { content: (ctx.content = 'message-content') }
  73. ctx.UserInfoManager.promises.getPersonalInfo = sinon
  74. .stub()
  75. .resolves((ctx.user = { unformatted: 'user' }))
  76. ctx.UserInfoController.formatPersonalInfo = sinon
  77. .stub()
  78. .returns((ctx.formatted_user = { formatted: 'user' }))
  79. ctx.ChatApiHandler.promises.sendGlobalMessage = sinon
  80. .stub()
  81. .resolves((ctx.message = { mock: 'message', user_id: ctx.user_id }))
  82. await ctx.ChatController.sendMessage(ctx.req, ctx.res)
  83. })
  84. it('should look up the user', function (ctx) {
  85. ctx.UserInfoManager.promises.getPersonalInfo
  86. .calledWith(ctx.user_id)
  87. .should.equal(true)
  88. })
  89. it('should format and inject the user into the message', function (ctx) {
  90. ctx.UserInfoController.formatPersonalInfo
  91. .calledWith(ctx.user)
  92. .should.equal(true)
  93. ctx.message.user.should.deep.equal(ctx.formatted_user)
  94. })
  95. it('should tell the chat handler about the message', function (ctx) {
  96. ctx.ChatApiHandler.promises.sendGlobalMessage
  97. .calledWith(ctx.project_id, ctx.user_id, ctx.content)
  98. .should.equal(true)
  99. })
  100. it('should tell the editor real time controller about the update with the data from the chat handler', function (ctx) {
  101. ctx.EditorRealTimeController.emitToRoom
  102. .calledWith(ctx.project_id, 'new-chat-message', ctx.message)
  103. .should.equal(true)
  104. })
  105. it('should return a 204 status code', function (ctx) {
  106. ctx.res.sendStatus.calledWith(204).should.equal(true)
  107. })
  108. })
  109. describe('getMessages', function () {
  110. beforeEach(async function (ctx) {
  111. ctx.req.query = {
  112. limit: (ctx.limit = '30'),
  113. before: (ctx.before = '12345'),
  114. }
  115. ctx.ChatManager.promises.injectUserInfoIntoThreads = sinon
  116. .stub()
  117. .resolves()
  118. ctx.ChatApiHandler.promises.getGlobalMessages = sinon
  119. .stub()
  120. .resolves((ctx.messages = ['mock', 'messages']))
  121. await ctx.ChatController.getMessages(ctx.req, ctx.res)
  122. })
  123. it('should ask the chat handler about the request', function (ctx) {
  124. ctx.ChatApiHandler.promises.getGlobalMessages
  125. .calledWith(ctx.project_id, ctx.limit, ctx.before)
  126. .should.equal(true)
  127. })
  128. it('should return the messages', function (ctx) {
  129. ctx.res.json.calledWith(ctx.messages).should.equal(true)
  130. })
  131. })
  132. })