DocumentControllerTests.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /* eslint-disable
  2. max-len,
  3. no-return-assign,
  4. no-unused-vars,
  5. */
  6. // TODO: This file was created by bulk-decaffeinate.
  7. // Fix any style issues and re-enable lint.
  8. /*
  9. * decaffeinate suggestions:
  10. * DS102: Remove unnecessary code created because of implicit returns
  11. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  12. */
  13. const sinon = require('sinon')
  14. const { expect } = require('chai')
  15. const modulePath =
  16. '../../../../app/src/Features/Documents/DocumentController.js'
  17. const SandboxedModule = require('sandboxed-module')
  18. const events = require('events')
  19. const MockRequest = require('../helpers/MockRequest')
  20. const MockResponse = require('../helpers/MockResponse')
  21. const Errors = require('../../../../app/src/Features/Errors/Errors')
  22. describe('DocumentController', function () {
  23. beforeEach(function () {
  24. this.DocumentController = SandboxedModule.require(modulePath, {
  25. requires: {
  26. '../Project/ProjectGetter': (this.ProjectGetter = {}),
  27. '../Project/ProjectLocator': (this.ProjectLocator = {}),
  28. '../Project/ProjectEntityHandler': (this.ProjectEntityHandler = {}),
  29. '../Project/ProjectEntityUpdateHandler': (this.ProjectEntityUpdateHandler = {}),
  30. },
  31. })
  32. this.res = new MockResponse()
  33. this.req = new MockRequest()
  34. this.next = sinon.stub()
  35. this.project_id = 'project-id-123'
  36. this.doc_id = 'doc-id-123'
  37. this.doc_lines = ['one', 'two', 'three']
  38. this.version = 42
  39. this.ranges = { mock: 'ranges' }
  40. this.pathname = '/a/b/c/file.tex'
  41. this.lastUpdatedAt = new Date().getTime()
  42. this.lastUpdatedBy = 'fake-last-updater-id'
  43. return (this.rev = 5)
  44. })
  45. describe('getDocument', function () {
  46. beforeEach(function () {
  47. return (this.req.params = {
  48. Project_id: this.project_id,
  49. doc_id: this.doc_id,
  50. })
  51. })
  52. describe('when the project exists without project history enabled', function () {
  53. beforeEach(function () {
  54. this.project = { _id: this.project_id }
  55. return (this.ProjectGetter.getProject = sinon
  56. .stub()
  57. .callsArgWith(2, null, this.project))
  58. })
  59. describe('when the document exists', function () {
  60. beforeEach(function () {
  61. this.doc = { _id: this.doc_id }
  62. this.ProjectLocator.findElement = sinon
  63. .stub()
  64. .callsArgWith(1, null, this.doc, { fileSystem: this.pathname })
  65. this.ProjectEntityHandler.getDoc = sinon
  66. .stub()
  67. .callsArgWith(
  68. 2,
  69. null,
  70. this.doc_lines,
  71. this.rev,
  72. this.version,
  73. this.ranges
  74. )
  75. return this.DocumentController.getDocument(
  76. this.req,
  77. this.res,
  78. this.next
  79. )
  80. })
  81. it('should get the project', function () {
  82. return this.ProjectGetter.getProject
  83. .calledWith(this.project_id, { rootFolder: true, overleaf: true })
  84. .should.equal(true)
  85. })
  86. it('should get the pathname of the document', function () {
  87. return this.ProjectLocator.findElement
  88. .calledWith({
  89. project: this.project,
  90. element_id: this.doc_id,
  91. type: 'doc',
  92. })
  93. .should.equal(true)
  94. })
  95. it('should get the document content', function () {
  96. return this.ProjectEntityHandler.getDoc
  97. .calledWith(this.project_id, this.doc_id)
  98. .should.equal(true)
  99. })
  100. it('should return the document data to the client as JSON', function () {
  101. this.res.type.should.equal('application/json')
  102. return this.res.body.should.equal(
  103. JSON.stringify({
  104. lines: this.doc_lines,
  105. version: this.version,
  106. ranges: this.ranges,
  107. pathname: this.pathname,
  108. })
  109. )
  110. })
  111. })
  112. describe("when the document doesn't exist", function () {
  113. beforeEach(function () {
  114. this.ProjectLocator.findElement = sinon
  115. .stub()
  116. .callsArgWith(1, new Errors.NotFoundError('not found'))
  117. return this.DocumentController.getDocument(
  118. this.req,
  119. this.res,
  120. this.next
  121. )
  122. })
  123. it('should call next with the NotFoundError', function () {
  124. return this.next
  125. .calledWith(sinon.match.instanceOf(Errors.NotFoundError))
  126. .should.equal(true)
  127. })
  128. })
  129. })
  130. describe('when project exists with project history enabled', function () {
  131. beforeEach(function () {
  132. this.doc = { _id: this.doc_id }
  133. this.projectHistoryId = 1234
  134. this.projectHistoryDisplay = true
  135. this.projectHistoryType = 'project-history'
  136. this.project = {
  137. _id: this.project_id,
  138. overleaf: {
  139. history: {
  140. id: this.projectHistoryId,
  141. display: this.projectHistoryDisplay,
  142. },
  143. },
  144. }
  145. this.ProjectGetter.getProject = sinon
  146. .stub()
  147. .callsArgWith(2, null, this.project)
  148. this.ProjectLocator.findElement = sinon
  149. .stub()
  150. .callsArgWith(1, null, this.doc, { fileSystem: this.pathname })
  151. this.ProjectEntityHandler.getDoc = sinon
  152. .stub()
  153. .callsArgWith(
  154. 2,
  155. null,
  156. this.doc_lines,
  157. this.rev,
  158. this.version,
  159. this.ranges
  160. )
  161. return this.DocumentController.getDocument(
  162. this.req,
  163. this.res,
  164. this.next
  165. )
  166. })
  167. it('should return the history id and display setting to the client as JSON', function () {
  168. this.res.type.should.equal('application/json')
  169. return this.res.body.should.equal(
  170. JSON.stringify({
  171. lines: this.doc_lines,
  172. version: this.version,
  173. ranges: this.ranges,
  174. pathname: this.pathname,
  175. projectHistoryId: this.projectHistoryId,
  176. projectHistoryType: this.projectHistoryType,
  177. })
  178. )
  179. })
  180. })
  181. describe('when the project does not exist', function () {
  182. beforeEach(function () {
  183. this.ProjectGetter.getProject = sinon.stub().callsArgWith(2, null, null)
  184. return this.DocumentController.getDocument(
  185. this.req,
  186. this.res,
  187. this.next
  188. )
  189. })
  190. it('returns a 404', function () {
  191. return this.res.statusCode.should.equal(404)
  192. })
  193. })
  194. })
  195. describe('setDocument', function () {
  196. beforeEach(function () {
  197. return (this.req.params = {
  198. Project_id: this.project_id,
  199. doc_id: this.doc_id,
  200. })
  201. })
  202. describe('when the document exists', function () {
  203. beforeEach(function () {
  204. this.ProjectEntityUpdateHandler.updateDocLines = sinon.stub().yields()
  205. this.req.body = {
  206. lines: this.doc_lines,
  207. version: this.version,
  208. ranges: this.ranges,
  209. lastUpdatedAt: this.lastUpdatedAt,
  210. lastUpdatedBy: this.lastUpdatedBy,
  211. }
  212. return this.DocumentController.setDocument(
  213. this.req,
  214. this.res,
  215. this.next
  216. )
  217. })
  218. it('should update the document in Mongo', function () {
  219. return sinon.assert.calledWith(
  220. this.ProjectEntityUpdateHandler.updateDocLines,
  221. this.project_id,
  222. this.doc_id,
  223. this.doc_lines,
  224. this.version,
  225. this.ranges,
  226. this.lastUpdatedAt,
  227. this.lastUpdatedBy
  228. )
  229. })
  230. it('should return a successful response', function () {
  231. return this.res.success.should.equal(true)
  232. })
  233. })
  234. describe("when the document doesn't exist", function () {
  235. beforeEach(function () {
  236. this.ProjectEntityUpdateHandler.updateDocLines = sinon
  237. .stub()
  238. .yields(new Errors.NotFoundError('document does not exist'))
  239. this.req.body = { lines: this.doc_lines }
  240. return this.DocumentController.setDocument(
  241. this.req,
  242. this.res,
  243. this.next
  244. )
  245. })
  246. it('should call next with the NotFoundError', function () {
  247. return this.next
  248. .calledWith(sinon.match.instanceOf(Errors.NotFoundError))
  249. .should.equal(true)
  250. })
  251. })
  252. })
  253. })