ProjectLocatorTests.coffee 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. spies = require('chai-spies')
  2. chai = require('chai').use(spies)
  3. assert = require('chai').assert
  4. should = chai.should()
  5. modulePath = "../../../../app/js/Features/Project/ProjectLocator"
  6. SandboxedModule = require('sandboxed-module')
  7. sinon = require('sinon')
  8. Errors = require "../../../../app/js/errors"
  9. expect = require("chai").expect
  10. Project = class Project
  11. project = _id : "1234566", rootFolder:[]
  12. rootDoc = name:"rootDoc", _id:"das239djd"
  13. doc1 = name:"otherDoc.txt", _id:"dsad2ddd"
  14. doc2 = name:"docname.txt", _id:"dsad2ddddd"
  15. file1 = name:"file1", _id:"dsa9lkdsad"
  16. subSubFile = name:"subSubFile", _id:"d1d2dk"
  17. subSubDoc = name:"subdoc.txt", _id:"321dmdwi"
  18. secondSubFolder = name:"secondSubFolder", _id:"dsa3e23", docs:[subSubDoc], fileRefs:[subSubFile], folders:[]
  19. subFolder = name:"subFolder", _id:"dsadsa93", folders:[secondSubFolder], docs:[], fileRefs:[]
  20. subFolder1 = name:"subFolder1", _id:"123asdjoij"
  21. rootFolder =
  22. _id : "123sdskd"
  23. docs:[doc1, doc2, null, rootDoc]
  24. fileRefs:[file1]
  25. folders:[subFolder1, subFolder]
  26. project.rootFolder[0] = rootFolder
  27. project.rootDoc_id = rootDoc._id
  28. describe 'project model', ->
  29. beforeEach ->
  30. Project.getProject = (project_id, fields, callback)=>
  31. callback(null, project)
  32. Project.findById = (project_id, callback)=>
  33. callback(null, project)
  34. @locator = SandboxedModule.require modulePath, requires:
  35. '../../models/Project':{Project:Project}
  36. '../../models/User':{User:@User}
  37. 'logger-sharelatex':
  38. log:->
  39. err:->
  40. warn: ->
  41. describe 'finding a doc', ->
  42. it 'finds one at the root level', (done)->
  43. @locator.findElement {project_id:project._id, element_id:doc2._id, type:"docs"}, (err, foundElement, path, parentFolder)->
  44. assert(!err?)
  45. foundElement._id.should.equal doc2._id
  46. path.fileSystem.should.equal "/#{doc2.name}"
  47. parentFolder._id.should.equal project.rootFolder[0]._id
  48. path.mongo.should.equal "rootFolder.0.docs.1"
  49. done()
  50. it 'when it is nested', (done)->
  51. @locator.findElement {project_id:project._id, element_id:subSubDoc._id, type:"doc"}, (err, foundElement, path, parentFolder)->
  52. assert(!err?)
  53. should.equal foundElement._id, subSubDoc._id
  54. path.fileSystem.should.equal "/#{subFolder.name}/#{secondSubFolder.name}/#{subSubDoc.name}"
  55. parentFolder._id.should.equal secondSubFolder._id
  56. path.mongo.should.equal "rootFolder.0.folders.1.folders.0.docs.0"
  57. done()
  58. it 'should give error if element could not be found', (done)->
  59. @locator.findElement {project_id:project._id, element_id:"ddsd432nj42", type:"docs"}, (err, foundElement, path, parentFolder)->
  60. err.should.deep.equal new Errors.NotFoundError("entity not found")
  61. done()
  62. describe 'finding a folder', ->
  63. it 'should return root folder when looking for root folder', (done)->
  64. @locator.findElement {project_id:project._id, element_id:rootFolder._id, type:"folder"}, (err, foundElement, path, parentFolder)->
  65. assert(!err)
  66. foundElement._id.should.equal rootFolder._id
  67. done()
  68. it 'when at root', (done)->
  69. @locator.findElement {project_id:project._id, element_id:subFolder._id, type:"folder"}, (err, foundElement, path, parentFolder)->
  70. assert(!err)
  71. foundElement._id.should.equal subFolder._id
  72. path.fileSystem.should.equal "/#{subFolder.name}"
  73. parentFolder._id.should.equal rootFolder._id
  74. path.mongo.should.equal "rootFolder.0.folders.1"
  75. done()
  76. it 'when deeply nested', (done)->
  77. @locator.findElement {project_id:project._id, element_id:secondSubFolder._id, type:"folder"}, (err, foundElement, path, parentFolder)->
  78. assert(!err)
  79. foundElement._id.should.equal secondSubFolder._id
  80. path.fileSystem.should.equal "/#{subFolder.name}/#{secondSubFolder.name}"
  81. parentFolder._id.should.equal subFolder._id
  82. path.mongo.should.equal "rootFolder.0.folders.1.folders.0"
  83. done()
  84. describe 'finding a file', ->
  85. it 'when at root', (done)->
  86. @locator.findElement {project_id:project._id, element_id:file1._id, type:"fileRefs"}, (err, foundElement, path, parentFolder)->
  87. assert(!err)
  88. foundElement._id.should.equal file1._id
  89. path.fileSystem.should.equal "/#{file1.name}"
  90. parentFolder._id.should.equal rootFolder._id
  91. path.mongo.should.equal "rootFolder.0.fileRefs.0"
  92. done()
  93. it 'when deeply nested', (done)->
  94. @locator.findElement {project_id:project._id, element_id:subSubFile._id, type:"fileRefs"}, (err, foundElement, path, parentFolder)->
  95. assert(!err)
  96. foundElement._id.should.equal subSubFile._id
  97. path.fileSystem.should.equal "/#{subFolder.name}/#{secondSubFolder.name}/#{subSubFile.name}"
  98. parentFolder._id.should.equal secondSubFolder._id
  99. path.mongo.should.equal "rootFolder.0.folders.1.folders.0.fileRefs.0"
  100. done()
  101. describe 'finding an element with wrong element type', ->
  102. it 'should add an s onto the element type', (done)->
  103. @locator.findElement {project_id:project._id, element_id:subSubDoc._id, type:"doc"}, (err, foundElement, path, parentFolder)->
  104. assert(!err)
  105. foundElement._id.should.equal subSubDoc._id
  106. done()
  107. it 'should convert file to fileRefs', (done)->
  108. @locator.findElement {project_id:project._id, element_id:file1._id, type:"fileRefs"}, (err, foundElement, path, parentFolder)->
  109. assert(!err)
  110. foundElement._id.should.equal file1._id
  111. done()
  112. describe 'should be able to take actual project as well as id', ->
  113. doc3 =
  114. _id:"123dsdj3"
  115. name:"doc3"
  116. rootFolder2 =
  117. _id : "123sddedskd"
  118. docs:[doc3]
  119. project2 =
  120. _id : "1234566"
  121. rootFolder:[rootFolder2]
  122. it 'should find doc in project', (done)->
  123. @locator.findElement {project:project2, element_id:doc3._id, type:"docs"}, (err, foundElement, path, parentFolder)->
  124. assert(!err?)
  125. foundElement._id.should.equal doc3._id
  126. path.fileSystem.should.equal "/#{doc3.name}"
  127. parentFolder._id.should.equal project2.rootFolder[0]._id
  128. path.mongo.should.equal "rootFolder.0.docs.0"
  129. done()
  130. describe 'finding root doc', ->
  131. it 'should return root doc when passed project', (done)->
  132. @locator.findRootDoc project, (err, doc)->
  133. assert !err?
  134. doc._id.should.equal rootDoc._id
  135. done()
  136. it 'should return root doc when passed project_id', (done)->
  137. @locator.findRootDoc project._id, (err, doc)->
  138. assert !err?
  139. doc._id.should.equal rootDoc._id
  140. done()
  141. describe 'findElementByPath', ->
  142. it 'should take a doc path and return the element for a root level document', (done)->
  143. path = "#{doc1.name}"
  144. @locator.findElementByPath project._id, path, (err, element)->
  145. element.should.deep.equal doc1
  146. done()
  147. it 'should take a doc path and return the element for a root level document with a starting slash', (done)->
  148. path = "/#{doc1.name}"
  149. @locator.findElementByPath project._id, path, (err, element)->
  150. element.should.deep.equal doc1
  151. done()
  152. it 'should take a doc path and return the element for a nested document', (done)->
  153. path = "#{subFolder.name}/#{secondSubFolder.name}/#{subSubDoc.name}"
  154. @locator.findElementByPath project._id, path, (err, element)->
  155. element.should.deep.equal subSubDoc
  156. done()
  157. it 'should take a file path and return the element for a root level document', (done)->
  158. path = "#{file1.name}"
  159. @locator.findElementByPath project._id, path, (err, element)->
  160. element.should.deep.equal file1
  161. done()
  162. it 'should take a file path and return the element for a nested document', (done)->
  163. path = "#{subFolder.name}/#{secondSubFolder.name}/#{subSubFile.name}"
  164. @locator.findElementByPath project._id, path, (err, element)->
  165. element.should.deep.equal subSubFile
  166. done()
  167. it 'should take a file path and return the element for a nested document case insenstive', (done)->
  168. path = "#{subFolder.name.toUpperCase()}/#{secondSubFolder.name.toUpperCase()}/#{subSubFile.name.toUpperCase()}"
  169. @locator.findElementByPath project._id, path, (err, element)->
  170. element.should.deep.equal subSubFile
  171. done()
  172. it 'should take a file path and return the element for a nested folder', (done)->
  173. path = "#{subFolder.name}/#{secondSubFolder.name}"
  174. @locator.findElementByPath project._id, path, (err, element)->
  175. element.should.deep.equal secondSubFolder
  176. done()
  177. it 'should take a file path and return the root folder', (done)->
  178. @locator.findElementByPath project._id, "/", (err, element)->
  179. element.should.deep.equal rootFolder
  180. done()
  181. it 'should return an error if the file can not be found inside know folder', (done)->
  182. @locator.findElementByPath project._id, "#{subFolder.name}/#{secondSubFolder.name}/exist.txt", (err, element)->
  183. err.should.not.equal undefined
  184. assert.equal element, undefined
  185. done()
  186. it 'should return an error if the file can not be found inside unknown folder', (done)->
  187. @locator.findElementByPath project._id, "this/does/not/exist.txt", (err, element)->
  188. err.should.not.equal undefined
  189. assert.equal element, undefined
  190. done()
  191. describe "where duplicate folder exists", ->
  192. beforeEach ->
  193. @duplicateFolder = {name:"duplicate1", _id:"1234", folders:[{
  194. name: "1"
  195. docs:[{name:"main.tex", _id:"456"}]
  196. folders: []
  197. fileRefs: []
  198. }], docs:[@doc = {name:"main.tex", _id:"456"}], fileRefs:[]}
  199. @project =
  200. rootFolder:[
  201. folders: [@duplicateFolder, @duplicateFolder]
  202. fileRefs: []
  203. docs: []
  204. ]
  205. Project.getProject = sinon.stub()
  206. Project.getProject.callsArgWith(2, null, @project)
  207. it "should not call the callback more than once", (done)->
  208. @locator.findElementByPath project._id, "#{@duplicateFolder.name}/#{@doc.name}", ->
  209. done() #mocha will throw exception if done called multiple times
  210. it "should not call the callback more than once when the path is longer than 1 level below the duplicate level", (done)->
  211. @locator.findElementByPath project._id, "#{@duplicateFolder.name}/1/main.tex", ->
  212. done() #mocha will throw exception if done called multiple times
  213. describe "with a null doc", ->
  214. beforeEach ->
  215. @project =
  216. rootFolder:[
  217. folders: []
  218. fileRefs: []
  219. docs: [{name:"main.tex"}, null, {name:"other.tex"}]
  220. ]
  221. Project.getProject = sinon.stub()
  222. Project.getProject.callsArgWith(2, null, @project)
  223. it "should not crash with a null", (done)->
  224. callback = sinon.stub()
  225. @locator.findElementByPath project._id, "/other.tex", (err, element)->
  226. element.name.should.equal "other.tex"
  227. done()
  228. describe "with a null project", ->
  229. beforeEach ->
  230. @project =
  231. rootFolder:[
  232. folders: []
  233. fileRefs: []
  234. docs: [{name:"main.tex"}, null, {name:"other.tex"}]
  235. ]
  236. Project.getProject = sinon.stub()
  237. Project.getProject.callsArgWith(2, null)
  238. it "should not crash with a null", (done)->
  239. callback = sinon.stub()
  240. @locator.findElementByPath project._id, "/other.tex", (err, element)->
  241. expect(err).to.exist
  242. done()
  243. describe 'finding a project by user_id and project name', ()->
  244. it 'should return the projet from an array case insenstive', (done)->
  245. user_id = "123jojoidns"
  246. stubbedProject = {name:"findThis"}
  247. projects = [{name:"notThis"}, {name:"wellll"}, stubbedProject, {name:"Noooo"}]
  248. Project.findAllUsersProjects = sinon.stub().callsArgWith(2, null, projects)
  249. @locator.findUsersProjectByName user_id, stubbedProject.name.toLowerCase(), (err, project)->
  250. project.should.equal stubbedProject
  251. done()
  252. it 'should search collab projects as well', (done)->
  253. user_id = "123jojoidns"
  254. stubbedProject = {name:"findThis"}
  255. projects = [{name:"notThis"}, {name:"wellll"}, {name:"Noooo"}]
  256. Project.findAllUsersProjects = sinon.stub().callsArgWith(2, null, projects, [stubbedProject])
  257. @locator.findUsersProjectByName user_id, stubbedProject.name.toLowerCase(), (err, project)->
  258. project.should.equal stubbedProject
  259. done()