DocManagerTests.coffee 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. SandboxedModule = require('sandboxed-module')
  2. sinon = require('sinon')
  3. chai = require('chai')
  4. chai.should()
  5. expect = chai.expect
  6. modulePath = require('path').join __dirname, '../../../app/js/DocManager'
  7. ObjectId = require("mongojs").ObjectId
  8. Errors = require "../../../app/js/Errors"
  9. describe "DocManager", ->
  10. beforeEach ->
  11. @DocManager = SandboxedModule.require modulePath, requires:
  12. "./MongoManager": @MongoManager = {}
  13. "logger-sharelatex": @logger = {log: sinon.stub(), warn:->}
  14. @doc_id = ObjectId().toString()
  15. @project_id = ObjectId().toString()
  16. @callback = sinon.stub()
  17. @stubbedError = new Error("blew up")
  18. describe "getDoc", ->
  19. beforeEach ->
  20. @project = { name: "mock-project" }
  21. @doc = { _id: @doc_id, lines: ["mock-lines"] }
  22. @docCollectionDoc = { _id: @doc_id, lines: ["mock-lines"] }
  23. describe "when the doc is in the doc collection not projects collection", ->
  24. beforeEach ->
  25. @MongoManager.findDoc = sinon.stub()
  26. @MongoManager.findProject = sinon.stub().callsArgWith(1, null, @project)
  27. @DocManager.findDocInProject = sinon.stub().callsArgWith(2, null, @doc, @mongoPath)
  28. it "should get the doc from the doc collection when it is present there", (done)->
  29. @MongoManager.findDoc.callsArgWith(1, null, @docCollectionDoc)
  30. @DocManager.getDoc @project_id, @doc_id, (err, doc)=>
  31. doc.should.equal @docCollectionDoc
  32. done()
  33. it "should return the error from find doc", (done)->
  34. @MongoManager.findDoc.callsArgWith(1, @stubbedError)
  35. @DocManager.getDoc @project_id, @doc_id, (err, doc)=>
  36. err.should.equal @stubbedError
  37. done()
  38. describe "when the project exists and the doc is in it", ->
  39. beforeEach ->
  40. @mongoPath = "mock.mongo.path"
  41. @MongoManager.findProject = sinon.stub().callsArgWith(1, null, @project)
  42. @MongoManager.findDoc = sinon.stub().callsArg(1)
  43. @DocManager.findDocInProject = sinon.stub().callsArgWith(2, null, @doc, @mongoPath)
  44. @DocManager.getDoc @project_id, @doc_id, @callback
  45. it "should get the project from the database", ->
  46. @MongoManager.findProject
  47. .calledWith(@project_id)
  48. .should.equal true
  49. it "should find the doc in the project", ->
  50. @DocManager.findDocInProject
  51. .calledWith(@project, @doc_id)
  52. .should.equal true
  53. it "should return the doc", ->
  54. @callback.calledWith(null, @doc, @mongoPath).should.equal true
  55. describe "when the project does not exist", ->
  56. beforeEach ->
  57. @MongoManager.findProject = sinon.stub().callsArgWith(1, null, null)
  58. @MongoManager.findDoc = sinon.stub().callsArg(1)
  59. @DocManager.findDocInProject = sinon.stub()
  60. @DocManager.getDoc @project_id, @doc_id, @callback
  61. it "should not try to find the doc in the project", ->
  62. @DocManager.findDocInProject.called.should.equal false
  63. it "should return a NotFoundError", ->
  64. @callback
  65. .calledWith(new Errors.NotFoundError("No such project: #{@project_id}"))
  66. .should.equal true
  67. describe "when the doc is deleted", ->
  68. beforeEach ->
  69. @MongoManager.findProject = sinon.stub().callsArgWith(1, null, @project)
  70. @DocManager.findDocInProject = sinon.stub().callsArgWith(2, null, null, null)
  71. @MongoManager.findDoc = sinon.stub().callsArgWith(1, null, @doc)
  72. @DocManager.getDoc @project_id, @doc_id, @callback
  73. it "should try to find the doc in the docs collection", ->
  74. @MongoManager.findDoc
  75. .calledWith(@doc_id)
  76. .should.equal true
  77. it "should return the doc", ->
  78. @callback
  79. .calledWith(null, @doc)
  80. .should.equal true
  81. describe "when the doc does not exist anywhere", ->
  82. beforeEach ->
  83. @MongoManager.findProject = sinon.stub().callsArgWith(1, null, @project)
  84. @DocManager.findDocInProject = sinon.stub().callsArgWith(2, null, null, null)
  85. @MongoManager.findDoc = sinon.stub().callsArgWith(1, null, null)
  86. @DocManager.getDoc @project_id, @doc_id, @callback
  87. it "should return a NotFoundError", ->
  88. @callback
  89. .calledWith(new Errors.NotFoundError("No such doc: #{@doc_id}"))
  90. .should.equal true
  91. describe "getAllDocs", ->
  92. describe "when the project exists", ->
  93. beforeEach ->
  94. @project = { name: "mock-project" }
  95. @docs = [{ _id: @doc_id, lines: ["mock-lines"] }]
  96. @mongoPath = "mock.mongo.path"
  97. @MongoManager.findProject = sinon.stub().callsArgWith(1, null, @project)
  98. @DocManager.findAllDocsInProject = sinon.stub().callsArgWith(1, null, @docs)
  99. @DocManager.getAllDocs @project_id, @callback
  100. it "should get the project from the database", ->
  101. @MongoManager.findProject
  102. .calledWith(@project_id)
  103. .should.equal true
  104. it "should find all the docs in the project", ->
  105. @DocManager.findAllDocsInProject
  106. .calledWith(@project)
  107. .should.equal true
  108. it "should return the docs", ->
  109. @callback.calledWith(null, @docs).should.equal true
  110. describe "when the project does not exist", ->
  111. beforeEach ->
  112. @MongoManager.findProject = sinon.stub().callsArgWith(1, null, null)
  113. @DocManager.findAllDocsInProject = sinon.stub()
  114. @DocManager.getAllDocs @project_id, @callback
  115. it "should not try to find the doc in the project", ->
  116. @DocManager.findAllDocsInProject.called.should.equal false
  117. it "should return a NotFoundError", ->
  118. @callback
  119. .calledWith(new Errors.NotFoundError("No such project: #{@project_id}"))
  120. .should.equal true
  121. describe "deleteDoc", ->
  122. describe "when the doc exists", ->
  123. beforeEach ->
  124. @lines = ["mock", "doc", "lines"]
  125. @rev = 77
  126. @DocManager.getDoc = sinon.stub().callsArgWith(2, null, {lines: @lines, rev:@rev})
  127. @MongoManager.upsertIntoDocCollection = sinon.stub().callsArg(4)
  128. @MongoManager.markDocAsDeleted = sinon.stub().callsArg(1)
  129. @DocManager.deleteDoc @project_id, @doc_id, @callback
  130. it "should get the doc", ->
  131. @DocManager.getDoc
  132. .calledWith(@project_id, @doc_id)
  133. .should.equal true
  134. it "should update the doc lines", ->
  135. @MongoManager.upsertIntoDocCollection
  136. .calledWith(@project_id, @doc_id, @lines, @rev)
  137. .should.equal true
  138. it "should mark doc as deleted", ->
  139. @MongoManager.markDocAsDeleted
  140. .calledWith(@doc_id)
  141. .should.equal true
  142. it "should return the callback", ->
  143. @callback.called.should.equal true
  144. describe "when the doc does not exist", ->
  145. beforeEach ->
  146. @DocManager.getDoc = sinon.stub().callsArgWith(2, null, null)
  147. @MongoManager.upsertIntoDocCollection = sinon.stub()
  148. @DocManager.deleteDoc @project_id, @doc_id, @callback
  149. it "should not try to insert a deleted doc", ->
  150. @MongoManager.upsertIntoDocCollection.called.should.equal false
  151. it "should return a NotFoundError", ->
  152. @callback
  153. .calledWith(new Errors.NotFoundError("No such doc: #{@doc_id}"))
  154. .should.equal true
  155. describe "updateDoc", ->
  156. beforeEach ->
  157. @oldDocLines = ["old", "doc", "lines"]
  158. @newDocLines = ["new", "doc", "lines"]
  159. @doc = { _id: @doc_id, lines: @oldDocLines, rev: @rev = 5 }
  160. @mongoPath = "mock.mongo.path"
  161. @MongoManager.updateDoc = sinon.stub().callsArg(3)
  162. @MongoManager.upsertIntoDocCollection = sinon.stub().callsArg(4)
  163. describe "when the doc lines have changed", ->
  164. beforeEach ->
  165. @DocManager.getDoc = sinon.stub().callsArgWith(2, null, @doc, @mongoPath)
  166. @DocManager.updateDoc @project_id, @doc_id, @newDocLines, @callback
  167. it "should get the existing doc", ->
  168. @DocManager.getDoc
  169. .calledWith(@project_id, @doc_id)
  170. .should.equal true
  171. it "should update the doc with the new doc lines", ->
  172. @MongoManager.updateDoc
  173. .calledWith(@project_id, @mongoPath, @newDocLines)
  174. .should.equal true
  175. it "should upsert the document to the doc collection", ->
  176. @MongoManager.upsertIntoDocCollection
  177. .calledWith(@project_id, @doc_id, @newDocLines, @rev)
  178. .should.equal true
  179. it "should log out the old and new doc lines", ->
  180. @logger.log
  181. .calledWith(
  182. project_id: @project_id
  183. doc_id: @doc_id
  184. oldDocLines: @oldDocLines
  185. newDocLines: @newDocLines
  186. rev: @doc.rev
  187. "updating doc lines"
  188. )
  189. .should.equal true
  190. it "should return the callback with the new rev", ->
  191. @callback.calledWith(null, true, @rev + 1).should.equal true
  192. describe "when the doc lines have not changed", ->
  193. beforeEach ->
  194. @DocManager.getDoc = sinon.stub().callsArgWith(2, null, @doc, @mongoPath)
  195. @DocManager.updateDoc @project_id, @doc_id, @oldDocLines.slice(), @callback
  196. it "should not update the doc", ->
  197. @MongoManager.updateDoc.called.should.equal false
  198. @MongoManager.upsertIntoDocCollection.called.should.equal false
  199. it "should return the callback with the existing rev", ->
  200. @callback.calledWith(null, false, @rev).should.equal true
  201. describe "when the doc does not exist", ->
  202. beforeEach ->
  203. @DocManager.getDoc = sinon.stub().callsArgWith(2, null, null, null)
  204. @DocManager.updateDoc @project_id, @doc_id, @newDocLines, @callback
  205. it "should not try to update the doc", ->
  206. @MongoManager.updateDoc.called.should.equal false
  207. @MongoManager.upsertIntoDocCollection.called.should.equal false
  208. it "should return a NotFoundError", ->
  209. @callback
  210. .calledWith(new Errors.NotFoundError("No such project/doc: #{@project_id}/#{@doc_id}"))
  211. .should.equal true
  212. describe "findDocInProject", ->
  213. it "should find the doc when it is in the root folder", (done) ->
  214. @DocManager.findDocInProject {
  215. rootFolder: [{
  216. docs: [{
  217. _id: ObjectId(@doc_id)
  218. }]
  219. }]
  220. }, @doc_id, (error, doc, mongoPath) =>
  221. expect(doc).to.deep.equal { _id: ObjectId(@doc_id) }
  222. mongoPath.should.equal "rootFolder.0.docs.0"
  223. done()
  224. it "should find the doc when it is in a sub folder", (done) ->
  225. @DocManager.findDocInProject {
  226. rootFolder: [{
  227. folders: [{
  228. docs: [{
  229. _id: ObjectId(@doc_id)
  230. }]
  231. }]
  232. }]
  233. }, @doc_id, (error, doc, mongoPath) =>
  234. expect(doc).to.deep.equal { _id: ObjectId(@doc_id) }
  235. mongoPath.should.equal "rootFolder.0.folders.0.docs.0"
  236. done()
  237. it "should find the doc when it there are other docs", (done) ->
  238. @DocManager.findDocInProject {
  239. rootFolder: [{
  240. folders: [{
  241. docs: [{
  242. _id: ObjectId()
  243. }]
  244. }, {
  245. docs: [{
  246. _id: ObjectId()
  247. }, {
  248. _id: ObjectId(@doc_id)
  249. }]
  250. }],
  251. docs: [{
  252. _id: ObjectId()
  253. }]
  254. }]
  255. }, @doc_id, (error, doc, mongoPath) =>
  256. expect(doc).to.deep.equal { _id: ObjectId(@doc_id) }
  257. mongoPath.should.equal "rootFolder.0.folders.1.docs.1"
  258. done()
  259. it "should return null when the doc doesn't exist", (done) ->
  260. @DocManager.findDocInProject {
  261. rootFolder: [{
  262. folders: [{
  263. docs: []
  264. }]
  265. }]
  266. }, @doc_id, (error, doc, mongoPath) =>
  267. expect(doc).to.be.null
  268. expect(mongoPath).to.be.null
  269. done()
  270. describe "findAllDocsInProject", ->
  271. it "should return all the docs", (done) ->
  272. @DocManager.findAllDocsInProject {
  273. rootFolder: [{
  274. docs: [
  275. @doc1 = { _id: ObjectId() }
  276. ],
  277. folders: [{
  278. docs: [
  279. @doc2 = { _id: ObjectId() }
  280. ]
  281. }, {
  282. docs: [
  283. @doc3 = { _id: ObjectId() }
  284. @doc4 = { _id: ObjectId() }
  285. ]
  286. }]
  287. }]
  288. }, (error, docs) =>
  289. expect(docs).to.deep.equal [@doc1, @doc2, @doc3, @doc4]
  290. done()