HttpControllerTests.coffee 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. SandboxedModule = require('sandboxed-module')
  2. assert = require("chai").assert
  3. sinon = require('sinon')
  4. chai = require('chai')
  5. chai.should()
  6. expect = chai.expect
  7. modulePath = require('path').join __dirname, '../../../app/js/HttpController'
  8. ObjectId = require("mongojs").ObjectId
  9. describe "HttpController", ->
  10. beforeEach ->
  11. @HttpController = SandboxedModule.require modulePath, requires:
  12. "./DocManager": @DocManager = {}
  13. "./DocArchiveManager": @DocArchiveManager = {}
  14. "logger-sharelatex": @logger = { log: sinon.stub(), error: sinon.stub() }
  15. "./HealthChecker": {}
  16. @res = { send: sinon.stub(), json: sinon.stub(), setHeader:sinon.stub() }
  17. @req = { query:{}}
  18. @next = sinon.stub()
  19. @project_id = "mock-project-id"
  20. @doc_id = "mock-doc-id"
  21. @doc = {
  22. _id: @doc_id
  23. lines: ["mock", "lines", " here", "", "", " spaces "]
  24. version: 42
  25. rev: 5
  26. }
  27. @deletedDoc = {
  28. deleted:true
  29. _id: @doc_id
  30. lines: ["mock", "lines", " here", "", "", " spaces "]
  31. version: 42
  32. rev: 5
  33. }
  34. describe "getDoc", ->
  35. describe "without deleted docs", ->
  36. beforeEach ->
  37. @req.params =
  38. project_id: @project_id
  39. doc_id: @doc_id
  40. @DocManager.getFullDoc = sinon.stub().callsArgWith(2, null, @doc)
  41. @HttpController.getDoc @req, @res, @next
  42. it "should get the document with the version (including deleted)", ->
  43. @DocManager.getFullDoc
  44. .calledWith(@project_id, @doc_id)
  45. .should.equal true
  46. it "should return the doc as JSON", ->
  47. @res.json
  48. .calledWith({
  49. _id: @doc_id
  50. lines: @doc.lines
  51. rev: @doc.rev
  52. version: @doc.version
  53. })
  54. .should.equal true
  55. describe "which is deleted", ->
  56. beforeEach ->
  57. @req.params =
  58. project_id: @project_id
  59. doc_id: @doc_id
  60. @DocManager.getFullDoc = sinon.stub().callsArgWith(2, null, @deletedDoc)
  61. it "should get the doc from the doc manager", ->
  62. @HttpController.getDoc @req, @res, @next
  63. @DocManager.getFullDoc.calledWith(@project_id, @doc_id).should.equal true
  64. it "should return 404 if the query string delete is not set ", ->
  65. @HttpController.getDoc @req, @res, @next
  66. @res.send.calledWith(404).should.equal true
  67. it "should return the doc as JSON if include_deleted is set to true", ->
  68. @req.query.include_deleted = "true"
  69. @HttpController.getDoc @req, @res, @next
  70. @res.json
  71. .calledWith({
  72. _id: @doc_id
  73. lines: @doc.lines
  74. rev: @doc.rev
  75. deleted: true
  76. version: @doc.version
  77. })
  78. .should.equal true
  79. describe "getRawDoc", ->
  80. beforeEach ->
  81. @req.params =
  82. project_id: @project_id
  83. doc_id: @doc_id
  84. @DocManager.getDocLines = sinon.stub().callsArgWith(2, null, @doc)
  85. @HttpController.getRawDoc @req, @res, @next
  86. it "should get the document without the version", ->
  87. @DocManager.getDocLines
  88. .calledWith(@project_id, @doc_id)
  89. .should.equal true
  90. it "should set the content type header", ->
  91. @res.setHeader.calledWith('content-type', 'text/plain').should.equal true
  92. it "should send the raw version of the doc", ->
  93. assert.deepEqual @res.send.args[0][0], "#{@doc.lines[0]}\n#{@doc.lines[1]}\n#{@doc.lines[2]}\n#{@doc.lines[3]}\n#{@doc.lines[4]}\n#{@doc.lines[5]}"
  94. describe "getAllDocs", ->
  95. describe "normally", ->
  96. beforeEach ->
  97. @req.params =
  98. project_id: @project_id
  99. @docs = [{
  100. _id: ObjectId()
  101. lines: ["mock", "lines", "one"]
  102. rev: 2
  103. }, {
  104. _id: ObjectId()
  105. lines: ["mock", "lines", "two"]
  106. rev: 4
  107. }]
  108. @DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, @docs)
  109. @HttpController.getAllDocs @req, @res, @next
  110. it "should get all the (non-deleted) docs", ->
  111. @DocManager.getAllNonDeletedDocs
  112. .calledWith(@project_id, {lines: true, rev: true})
  113. .should.equal true
  114. it "should return the doc as JSON", ->
  115. @res.json
  116. .calledWith([{
  117. _id: @docs[0]._id.toString()
  118. lines: @docs[0].lines
  119. rev: @docs[0].rev
  120. }, {
  121. _id: @docs[1]._id.toString()
  122. lines: @docs[1].lines
  123. rev: @docs[1].rev
  124. }])
  125. .should.equal true
  126. describe "with a null doc", ->
  127. beforeEach ->
  128. @req.params =
  129. project_id: @project_id
  130. @docs = [{
  131. _id: ObjectId()
  132. lines: ["mock", "lines", "one"]
  133. rev: 2
  134. },
  135. null,
  136. {
  137. _id: ObjectId()
  138. lines: ["mock", "lines", "two"]
  139. rev: 4
  140. }]
  141. @DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, @docs)
  142. @HttpController.getAllDocs @req, @res, @next
  143. it "should return the non null docs as JSON", ->
  144. @res.json
  145. .calledWith([{
  146. _id: @docs[0]._id.toString()
  147. lines: @docs[0].lines
  148. rev: @docs[0].rev
  149. }, {
  150. _id: @docs[2]._id.toString()
  151. lines: @docs[2].lines
  152. rev: @docs[2].rev
  153. }])
  154. .should.equal true
  155. it "should log out an error", ->
  156. @logger.error
  157. .calledWith(
  158. err: sinon.match.has('message', "null doc")
  159. project_id: @project_id
  160. "encountered null doc"
  161. )
  162. .should.equal true
  163. describe "getAllRanges", ->
  164. describe "normally", ->
  165. beforeEach ->
  166. @req.params =
  167. project_id: @project_id
  168. @docs = [{
  169. _id: ObjectId()
  170. ranges: {"mock_ranges": "one"}
  171. }, {
  172. _id: ObjectId()
  173. ranges: {"mock_ranges": "two"}
  174. }]
  175. @DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, @docs)
  176. @HttpController.getAllRanges @req, @res, @next
  177. it "should get all the (non-deleted) doc ranges", ->
  178. @DocManager.getAllNonDeletedDocs
  179. .calledWith(@project_id, {ranges: true})
  180. .should.equal true
  181. it "should return the doc as JSON", ->
  182. @res.json
  183. .calledWith([{
  184. _id: @docs[0]._id.toString()
  185. ranges: @docs[0].ranges
  186. }, {
  187. _id: @docs[1]._id.toString()
  188. ranges: @docs[1].ranges
  189. }])
  190. .should.equal true
  191. describe "updateDoc", ->
  192. beforeEach ->
  193. @req.params =
  194. project_id: @project_id
  195. doc_id: @doc_id
  196. describe "when the doc lines exist and were updated", ->
  197. beforeEach ->
  198. @req.body =
  199. lines: @lines = ["hello", "world"]
  200. version: @version = 42
  201. ranges: @ranges = { changes: "mock" }
  202. @DocManager.updateDoc = sinon.stub().yields(null, true, @rev = 5)
  203. @HttpController.updateDoc @req, @res, @next
  204. it "should update the document", ->
  205. @DocManager.updateDoc
  206. .calledWith(@project_id, @doc_id, @lines, @version, @ranges)
  207. .should.equal true
  208. it "should return a modified status", ->
  209. @res.json
  210. .calledWith(modified: true, rev: @rev)
  211. .should.equal true
  212. describe "when the doc lines exist and were not updated", ->
  213. beforeEach ->
  214. @req.body =
  215. lines: @lines = ["hello", "world"]
  216. version: @version = 42
  217. ranges: {}
  218. @DocManager.updateDoc = sinon.stub().yields(null, false, @rev = 5)
  219. @HttpController.updateDoc @req, @res, @next
  220. it "should return a modified status", ->
  221. @res.json
  222. .calledWith(modified: false, rev: @rev)
  223. .should.equal true
  224. describe "when the doc lines are not provided", ->
  225. beforeEach ->
  226. @req.body = { version: 42, ranges: {} }
  227. @DocManager.updateDoc = sinon.stub().yields(null, false)
  228. @HttpController.updateDoc @req, @res, @next
  229. it "should not update the document", ->
  230. @DocManager.updateDoc.called.should.equal false
  231. it "should return a 400 (bad request) response", ->
  232. @res.send
  233. .calledWith(400)
  234. .should.equal true
  235. describe "when the doc version are not provided", ->
  236. beforeEach ->
  237. @req.body = { version: 42, lines: ["hello world"] }
  238. @DocManager.updateDoc = sinon.stub().yields(null, false)
  239. @HttpController.updateDoc @req, @res, @next
  240. it "should not update the document", ->
  241. @DocManager.updateDoc.called.should.equal false
  242. it "should return a 400 (bad request) response", ->
  243. @res.send
  244. .calledWith(400)
  245. .should.equal true
  246. describe "when the doc ranges is not provided", ->
  247. beforeEach ->
  248. @req.body = { lines : [ "foo" ], version: 42 }
  249. @DocManager.updateDoc = sinon.stub().yields(null, false)
  250. @HttpController.updateDoc @req, @res, @next
  251. it "should not update the document", ->
  252. @DocManager.updateDoc.called.should.equal false
  253. it "should return a 400 (bad request) response", ->
  254. @res.send
  255. .calledWith(400)
  256. .should.equal true
  257. describe "deleteDoc", ->
  258. beforeEach ->
  259. @req.params =
  260. project_id: @project_id
  261. doc_id: @doc_id
  262. @DocManager.deleteDoc = sinon.stub().callsArg(2)
  263. @HttpController.deleteDoc @req, @res, @next
  264. it "should delete the document", ->
  265. @DocManager.deleteDoc
  266. .calledWith(@project_id, @doc_id)
  267. .should.equal true
  268. it "should return a 204 (No Content)", ->
  269. @res.send
  270. .calledWith(204)
  271. .should.equal true
  272. describe "archiveAllDocs", ->
  273. beforeEach ->
  274. @req.params =
  275. project_id: @project_id
  276. @DocArchiveManager.archiveAllDocs = sinon.stub().callsArg(1)
  277. @HttpController.archiveAllDocs @req, @res, @next
  278. it "should archive the project", ->
  279. @DocArchiveManager.archiveAllDocs
  280. .calledWith(@project_id)
  281. .should.equal true
  282. it "should return a 204 (No Content)", ->
  283. @res.send
  284. .calledWith(204)
  285. .should.equal true