DocumentControllerTests.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. const sinon = require('sinon')
  2. const SandboxedModule = require('sandboxed-module')
  3. const MockRequest = require('../helpers/MockRequest')
  4. const MockResponse = require('../helpers/MockResponse')
  5. const Errors = require('../../../../app/src/Features/Errors/Errors')
  6. const MODULE_PATH =
  7. '../../../../app/src/Features/Documents/DocumentController.js'
  8. describe('DocumentController', function () {
  9. beforeEach(function () {
  10. this.res = new MockResponse()
  11. this.req = new MockRequest()
  12. this.next = sinon.stub()
  13. this.doc = { _id: 'doc-id-123' }
  14. this.doc_lines = ['one', 'two', 'three']
  15. this.version = 42
  16. this.ranges = { mock: 'ranges' }
  17. this.pathname = '/a/b/c/file.tex'
  18. this.lastUpdatedAt = new Date().getTime()
  19. this.lastUpdatedBy = 'fake-last-updater-id'
  20. this.rev = 5
  21. this.project = {
  22. _id: 'project-id-123',
  23. overleaf: {
  24. history: {
  25. id: 1234,
  26. display: true,
  27. },
  28. },
  29. }
  30. this.ProjectGetter = {
  31. promises: {
  32. getProject: sinon.stub().resolves(this.project),
  33. },
  34. }
  35. this.ProjectLocator = {
  36. promises: {
  37. findElement: sinon
  38. .stub()
  39. .resolves({ element: this.doc, path: { fileSystem: this.pathname } }),
  40. },
  41. }
  42. this.ProjectEntityHandler = {
  43. promises: {
  44. getDoc: sinon.stub().resolves({
  45. lines: this.doc_lines,
  46. rev: this.rev,
  47. version: this.version,
  48. ranges: this.ranges,
  49. }),
  50. },
  51. }
  52. this.ProjectEntityUpdateHandler = {
  53. promises: {
  54. updateDocLines: sinon.stub().resolves(),
  55. },
  56. }
  57. this.DocumentController = SandboxedModule.require(MODULE_PATH, {
  58. requires: {
  59. '../Project/ProjectGetter': this.ProjectGetter,
  60. '../Project/ProjectLocator': this.ProjectLocator,
  61. '../Project/ProjectEntityHandler': this.ProjectEntityHandler,
  62. '../Project/ProjectEntityUpdateHandler':
  63. this.ProjectEntityUpdateHandler,
  64. },
  65. })
  66. })
  67. describe('getDocument', function () {
  68. beforeEach(function () {
  69. this.req.params = {
  70. Project_id: this.project._id,
  71. doc_id: this.doc._id,
  72. }
  73. })
  74. describe('when project exists with project history enabled', function () {
  75. beforeEach(function (done) {
  76. this.res.callback = err => {
  77. done(err)
  78. }
  79. this.DocumentController.getDocument(this.req, this.res, this.next)
  80. })
  81. it('should return the history id and display setting to the client as JSON', function () {
  82. this.res.type.should.equal('application/json')
  83. this.res.body.should.equal(
  84. JSON.stringify({
  85. lines: this.doc_lines,
  86. version: this.version,
  87. ranges: this.ranges,
  88. pathname: this.pathname,
  89. projectHistoryId: this.project.overleaf.history.id,
  90. projectHistoryType: 'project-history',
  91. historyRangesSupport: false,
  92. })
  93. )
  94. })
  95. })
  96. describe('when the project does not exist', function () {
  97. beforeEach(function (done) {
  98. this.ProjectGetter.promises.getProject.resolves(null)
  99. this.res.callback = err => {
  100. done(err)
  101. }
  102. this.DocumentController.getDocument(this.req, this.res, this.next)
  103. })
  104. it('returns a 404', function () {
  105. this.res.statusCode.should.equal(404)
  106. })
  107. })
  108. })
  109. describe('setDocument', function () {
  110. beforeEach(function () {
  111. this.req.params = {
  112. Project_id: this.project._id,
  113. doc_id: this.doc._id,
  114. }
  115. })
  116. describe('when the document exists', function () {
  117. beforeEach(function (done) {
  118. this.req.body = {
  119. lines: this.doc_lines,
  120. version: this.version,
  121. ranges: this.ranges,
  122. lastUpdatedAt: this.lastUpdatedAt,
  123. lastUpdatedBy: this.lastUpdatedBy,
  124. }
  125. this.res.callback = err => {
  126. done(err)
  127. }
  128. this.DocumentController.setDocument(this.req, this.res, this.next)
  129. })
  130. it('should update the document in Mongo', function () {
  131. sinon.assert.calledWith(
  132. this.ProjectEntityUpdateHandler.promises.updateDocLines,
  133. this.project._id,
  134. this.doc._id,
  135. this.doc_lines,
  136. this.version,
  137. this.ranges,
  138. this.lastUpdatedAt,
  139. this.lastUpdatedBy
  140. )
  141. })
  142. it('should return a successful response', function () {
  143. this.res.success.should.equal(true)
  144. })
  145. })
  146. describe("when the document doesn't exist", function () {
  147. beforeEach(function (done) {
  148. this.ProjectEntityUpdateHandler.promises.updateDocLines.rejects(
  149. new Errors.NotFoundError('document does not exist')
  150. )
  151. this.req.body = { lines: this.doc_lines }
  152. this.next.callsFake(() => {
  153. done()
  154. })
  155. this.DocumentController.setDocument(this.req, this.res, this.next)
  156. })
  157. it('should call next with the NotFoundError', function () {
  158. this.next
  159. .calledWith(sinon.match.instanceOf(Errors.NotFoundError))
  160. .should.equal(true)
  161. })
  162. })
  163. })
  164. })