WebApiManagerTests.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /* eslint-disable
  2. no-return-assign,
  3. no-unused-vars,
  4. */
  5. // TODO: This file was created by bulk-decaffeinate.
  6. // Fix any style issues and re-enable lint.
  7. /*
  8. * decaffeinate suggestions:
  9. * DS102: Remove unnecessary code created because of implicit returns
  10. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  11. */
  12. const sinon = require('sinon')
  13. const modulePath = '../../../app/js/WebApiManager.js'
  14. const SandboxedModule = require('sandboxed-module')
  15. const { CodedError } = require('../../../app/js/Errors')
  16. describe('WebApiManager', function () {
  17. beforeEach(function () {
  18. this.project_id = 'project-id-123'
  19. this.user_id = 'user-id-123'
  20. this.user = { _id: this.user_id }
  21. this.callback = sinon.stub()
  22. return (this.WebApiManager = SandboxedModule.require(modulePath, {
  23. requires: {
  24. request: (this.request = {}),
  25. '@overleaf/settings': (this.settings = {
  26. apis: {
  27. web: {
  28. url: 'http://web.example.com',
  29. user: 'username',
  30. pass: 'password',
  31. },
  32. },
  33. }),
  34. },
  35. }))
  36. })
  37. return describe('joinProject', function () {
  38. describe('successfully', function () {
  39. beforeEach(function () {
  40. this.response = {
  41. project: { name: 'Test project' },
  42. privilegeLevel: 'owner',
  43. isRestrictedUser: true,
  44. isTokenMember: true,
  45. isInvitedMember: true,
  46. }
  47. this.request.post = sinon
  48. .stub()
  49. .callsArgWith(1, null, { statusCode: 200 }, this.response)
  50. return this.WebApiManager.joinProject(
  51. this.project_id,
  52. this.user,
  53. this.callback
  54. )
  55. })
  56. it('should send a request to web to join the project', function () {
  57. return this.request.post
  58. .calledWith({
  59. url: `${this.settings.apis.web.url}/project/${this.project_id}/join`,
  60. auth: {
  61. user: this.settings.apis.web.user,
  62. pass: this.settings.apis.web.pass,
  63. sendImmediately: true,
  64. },
  65. json: {
  66. userId: this.user_id,
  67. anonymousAccessToken: undefined,
  68. },
  69. jar: false,
  70. })
  71. .should.equal(true)
  72. })
  73. return it('should return the project, privilegeLevel, and restricted flag', function () {
  74. return this.callback
  75. .calledWith(
  76. null,
  77. this.response.project,
  78. this.response.privilegeLevel,
  79. {
  80. isRestrictedUser: this.response.isRestrictedUser,
  81. isTokenMember: this.response.isTokenMember,
  82. isInvitedMember: this.response.isInvitedMember,
  83. }
  84. )
  85. .should.equal(true)
  86. })
  87. })
  88. describe('with anon user', function () {
  89. beforeEach(function () {
  90. this.user_id = 'anonymous-user'
  91. this.token = 'a-ro-token'
  92. this.user = {
  93. _id: this.user_id,
  94. anonymousAccessToken: this.token,
  95. }
  96. this.response = {
  97. project: { name: 'Test project' },
  98. privilegeLevel: 'readOnly',
  99. isRestrictedUser: true,
  100. isTokenMember: false,
  101. isInvitedMember: false,
  102. }
  103. this.request.post = sinon
  104. .stub()
  105. .yields(null, { statusCode: 200 }, this.response)
  106. this.WebApiManager.joinProject(
  107. this.project_id,
  108. this.user,
  109. this.callback
  110. )
  111. })
  112. it('should send a request to web to join the project', function () {
  113. this.request.post.should.have.been.calledWith({
  114. url: `${this.settings.apis.web.url}/project/${this.project_id}/join`,
  115. auth: {
  116. user: this.settings.apis.web.user,
  117. pass: this.settings.apis.web.pass,
  118. sendImmediately: true,
  119. },
  120. json: {
  121. userId: this.user_id,
  122. anonymousAccessToken: this.token,
  123. },
  124. jar: false,
  125. })
  126. })
  127. it('should return the project, privilegeLevel, and restricted flag', function () {
  128. this.callback.should.have.been.calledWith(
  129. null,
  130. this.response.project,
  131. this.response.privilegeLevel,
  132. {
  133. isRestrictedUser: this.response.isRestrictedUser,
  134. isTokenMember: this.response.isTokenMember,
  135. isInvitedMember: this.response.isInvitedMember,
  136. }
  137. )
  138. })
  139. })
  140. describe('when web replies with a 403', function () {
  141. beforeEach(function () {
  142. this.request.post = sinon
  143. .stub()
  144. .callsArgWith(1, null, { statusCode: 403 }, null)
  145. this.WebApiManager.joinProject(
  146. this.project_id,
  147. this.user_id,
  148. this.callback
  149. )
  150. })
  151. it('should call the callback with an error', function () {
  152. this.callback
  153. .calledWith(
  154. sinon.match({
  155. message: 'not authorized',
  156. })
  157. )
  158. .should.equal(true)
  159. })
  160. })
  161. describe('when web replies with a 404', function () {
  162. beforeEach(function () {
  163. this.request.post = sinon
  164. .stub()
  165. .callsArgWith(1, null, { statusCode: 404 }, null)
  166. this.WebApiManager.joinProject(
  167. this.project_id,
  168. this.user_id,
  169. this.callback
  170. )
  171. })
  172. it('should call the callback with an error', function () {
  173. this.callback
  174. .calledWith(
  175. sinon.match({
  176. message: 'project not found',
  177. info: { code: 'ProjectNotFound' },
  178. })
  179. )
  180. .should.equal(true)
  181. })
  182. })
  183. describe('with an error from web', function () {
  184. beforeEach(function () {
  185. this.request.post = sinon
  186. .stub()
  187. .callsArgWith(1, null, { statusCode: 500 }, null)
  188. return this.WebApiManager.joinProject(
  189. this.project_id,
  190. this.user_id,
  191. this.callback
  192. )
  193. })
  194. return it('should call the callback with an error', function () {
  195. return this.callback
  196. .calledWith(
  197. sinon.match({
  198. message: 'non-success status code from web',
  199. info: { statusCode: 500 },
  200. })
  201. )
  202. .should.equal(true)
  203. })
  204. })
  205. describe('with no data from web', function () {
  206. beforeEach(function () {
  207. this.request.post = sinon
  208. .stub()
  209. .callsArgWith(1, null, { statusCode: 200 }, null)
  210. return this.WebApiManager.joinProject(
  211. this.project_id,
  212. this.user_id,
  213. this.callback
  214. )
  215. })
  216. return it('should call the callback with an error', function () {
  217. return this.callback
  218. .calledWith(
  219. sinon.match({
  220. message: 'no data returned from joinProject request',
  221. })
  222. )
  223. .should.equal(true)
  224. })
  225. })
  226. return describe('when the project is over its rate limit', function () {
  227. beforeEach(function () {
  228. this.request.post = sinon
  229. .stub()
  230. .callsArgWith(1, null, { statusCode: 429 }, null)
  231. return this.WebApiManager.joinProject(
  232. this.project_id,
  233. this.user_id,
  234. this.callback
  235. )
  236. })
  237. return it('should call the callback with a TooManyRequests error code', function () {
  238. return this.callback
  239. .calledWith(
  240. sinon.match({
  241. message: 'rate-limit hit when joining project',
  242. info: {
  243. code: 'TooManyRequests',
  244. },
  245. })
  246. )
  247. .should.equal(true)
  248. })
  249. })
  250. })
  251. })