UserInfoControllerTests.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. const sinon = require('sinon')
  2. const { expect } = require('chai')
  3. const modulePath = '../../../../app/src/Features/User/UserInfoController.js'
  4. const SandboxedModule = require('sandboxed-module')
  5. const MockResponse = require('../helpers/MockResponse')
  6. const MockRequest = require('../helpers/MockRequest')
  7. const { ObjectId } = require('mongodb-legacy')
  8. describe('UserInfoController', function () {
  9. beforeEach(function () {
  10. this.UserDeleter = { deleteUser: sinon.stub().callsArgWith(1) }
  11. this.UserUpdater = { updatePersonalInfo: sinon.stub() }
  12. this.UserGetter = {
  13. promises: {
  14. getUserFeatures: sinon.stub(),
  15. },
  16. }
  17. this.UserInfoController = SandboxedModule.require(modulePath, {
  18. requires: {
  19. 'mongodb-legacy': { ObjectId },
  20. './UserGetter': this.UserGetter,
  21. './UserUpdater': this.UserUpdater,
  22. './UserDeleter': this.UserDeleter,
  23. '../Authentication/SessionManager': (this.SessionManager = {
  24. getLoggedInUserId: sinon.stub(),
  25. }),
  26. },
  27. })
  28. this.req = new MockRequest()
  29. this.res = new MockResponse()
  30. this.next = sinon.stub()
  31. })
  32. describe('getPersonalInfo', function () {
  33. describe('when the user exists with mongo id', function () {
  34. beforeEach(function () {
  35. this.user_id = new ObjectId().toString()
  36. this.user = { _id: new ObjectId(this.user_id) }
  37. this.req.params = { user_id: this.user_id }
  38. this.UserGetter.getUser = sinon.stub().callsArgWith(2, null, this.user)
  39. this.UserInfoController.sendFormattedPersonalInfo = sinon.stub()
  40. this.UserInfoController.getPersonalInfo(this.req, this.res, this.next)
  41. })
  42. it('should look up the user in the database', function () {
  43. this.UserGetter.getUser
  44. .calledWith(
  45. { _id: new ObjectId(this.user_id) },
  46. { _id: true, first_name: true, last_name: true, email: true }
  47. )
  48. .should.equal(true)
  49. })
  50. })
  51. describe('when the user exists with overleaf id', function () {
  52. beforeEach(function () {
  53. this.user_id = 12345
  54. this.user = {
  55. _id: new ObjectId(),
  56. overleaf: {
  57. id: this.user_id,
  58. },
  59. }
  60. this.req.params = { user_id: this.user_id.toString() }
  61. this.UserGetter.getUser = sinon.stub().callsArgWith(2, null, this.user)
  62. this.UserInfoController.getPersonalInfo(this.req, this.res, this.next)
  63. })
  64. it('should look up the user in the database', function () {
  65. this.UserGetter.getUser
  66. .calledWith(
  67. { 'overleaf.id': this.user_id },
  68. { _id: true, first_name: true, last_name: true, email: true }
  69. )
  70. .should.equal(true)
  71. })
  72. })
  73. describe('when the user does not exist', function () {
  74. beforeEach(function () {
  75. this.user_id = new ObjectId().toString()
  76. this.req.params = { user_id: this.user_id }
  77. this.UserGetter.getUser = sinon.stub().callsArgWith(2, null, null)
  78. this.UserInfoController.getPersonalInfo(this.req, this.res, this.next)
  79. })
  80. it('should return 404 to the client', function () {
  81. this.res.statusCode.should.equal(404)
  82. })
  83. })
  84. describe('when the user id is invalid', function () {
  85. beforeEach(function () {
  86. this.user_id = 'invalid'
  87. this.req.params = { user_id: this.user_id }
  88. this.UserGetter.getUser = sinon.stub().callsArgWith(2, null, null)
  89. this.UserInfoController.getPersonalInfo(this.req, this.res, this.next)
  90. })
  91. it('should return 400 to the client', function () {
  92. this.res.statusCode.should.equal(400)
  93. })
  94. })
  95. })
  96. describe('sendFormattedPersonalInfo', function () {
  97. beforeEach(function () {
  98. this.user = {
  99. _id: new ObjectId(),
  100. first_name: 'Douglas',
  101. last_name: 'Adams',
  102. email: 'doug@overleaf.com',
  103. }
  104. this.formattedInfo = {
  105. id: this.user._id.toString(),
  106. first_name: this.user.first_name,
  107. last_name: this.user.last_name,
  108. email: this.user.email,
  109. }
  110. this.UserInfoController.sendFormattedPersonalInfo(this.user, this.res)
  111. })
  112. it('should send the formatted details back to the client', function () {
  113. this.res.body.should.equal(JSON.stringify(this.formattedInfo))
  114. })
  115. })
  116. describe('formatPersonalInfo', function () {
  117. it('should return the correctly formatted data', function () {
  118. this.user = {
  119. _id: new ObjectId(),
  120. first_name: 'Douglas',
  121. last_name: 'Adams',
  122. email: 'doug@overleaf.com',
  123. password: 'should-not-get-included',
  124. signUpDate: new Date(),
  125. role: 'student',
  126. institution: 'sheffield',
  127. }
  128. expect(
  129. this.UserInfoController.formatPersonalInfo(this.user)
  130. ).to.deep.equal({
  131. id: this.user._id.toString(),
  132. first_name: this.user.first_name,
  133. last_name: this.user.last_name,
  134. email: this.user.email,
  135. signUpDate: this.user.signUpDate,
  136. role: this.user.role,
  137. institution: this.user.institution,
  138. })
  139. })
  140. })
  141. describe('getUserFeatures', function () {
  142. describe('when the user is logged in', function () {
  143. beforeEach(async function () {
  144. this.user_id = new ObjectId().toString()
  145. this.features = {
  146. collaborators: 10,
  147. trackChanges: true,
  148. references: true,
  149. }
  150. this.SessionManager.getLoggedInUserId.returns(this.user_id)
  151. this.UserGetter.promises.getUserFeatures.resolves(this.features)
  152. await this.UserInfoController.getUserFeatures(
  153. this.req,
  154. this.res,
  155. this.next
  156. )
  157. })
  158. it('should fetch the user features', function () {
  159. expect(this.UserGetter.promises.getUserFeatures.callCount).to.equal(1)
  160. expect(
  161. this.UserGetter.promises.getUserFeatures.calledWith(this.user_id)
  162. ).to.equal(true)
  163. })
  164. it('should return the features as JSON', function () {
  165. expect(this.res.json.callCount).to.equal(1)
  166. expect(this.res.json.calledWith(this.features)).to.equal(true)
  167. })
  168. })
  169. describe('when the user is not logged in', function () {
  170. beforeEach(async function () {
  171. this.SessionManager.getLoggedInUserId.returns(null)
  172. await this.UserInfoController.getUserFeatures(
  173. this.req,
  174. this.res,
  175. this.next
  176. )
  177. })
  178. it('should call next with an error', function () {
  179. expect(this.next.callCount).to.equal(1)
  180. expect(this.next.firstCall.args[0]).to.be.an.instanceof(Error)
  181. expect(this.next.firstCall.args[0].message).to.equal(
  182. 'User is not logged in'
  183. )
  184. })
  185. })
  186. describe('when fetching features fails', function () {
  187. beforeEach(async function () {
  188. this.user_id = new ObjectId().toString()
  189. this.error = new Error('something went wrong')
  190. this.SessionManager.getLoggedInUserId.returns(this.user_id)
  191. this.UserGetter.promises.getUserFeatures.rejects(this.error)
  192. await this.UserInfoController.getUserFeatures(
  193. this.req,
  194. this.res,
  195. this.next
  196. )
  197. })
  198. it('should call next with the error', function () {
  199. expect(this.next.callCount).to.equal(1)
  200. expect(this.next.firstCall.args[0]).to.equal(this.error)
  201. })
  202. })
  203. })
  204. })