ProjectStructureTests.coffee 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. async = require "async"
  2. expect = require("chai").expect
  3. mkdirp = require "mkdirp"
  4. ObjectId = require("mongojs").ObjectId
  5. Path = require "path"
  6. fs = require "fs"
  7. Settings = require "settings-sharelatex"
  8. _ = require "underscore"
  9. ProjectGetter = require "../../../app/js/Features/Project/ProjectGetter.js"
  10. MockDocUpdaterApi = require './helpers/MockDocUpdaterApi'
  11. MockFileStoreApi = require './helpers/MockFileStoreApi'
  12. MockProjectHistoryApi = require './helpers/MockProjectHistoryApi'
  13. request = require "./helpers/request"
  14. User = require "./helpers/User"
  15. describe "ProjectStructureChanges", ->
  16. before (done) ->
  17. @owner = new User()
  18. @owner.login done
  19. describe "creating a project from the example template", ->
  20. before (done) ->
  21. MockDocUpdaterApi.clearProjectStructureUpdates()
  22. @owner.createProject "example-project", {template: "example"}, (error, project_id) =>
  23. throw error if error?
  24. @example_project_id = project_id
  25. done()
  26. it "should version creating a doc", ->
  27. updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).docUpdates
  28. expect(updates.length).to.equal(2)
  29. _.each updates, (update) =>
  30. expect(update.userId).to.equal(@owner._id)
  31. expect(update.docLines).to.be.a('string')
  32. expect(_.where(updates, pathname: "/main.tex").length).to.equal 1
  33. expect(_.where(updates, pathname: "/references.bib").length).to.equal 1
  34. it "should version creating a file", ->
  35. updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).fileUpdates
  36. expect(updates.length).to.equal(1)
  37. update = updates[0]
  38. expect(update.userId).to.equal(@owner._id)
  39. expect(update.pathname).to.equal("/universe.jpg")
  40. expect(update.url).to.be.a('string');
  41. describe "duplicating a project", ->
  42. before (done) ->
  43. MockDocUpdaterApi.clearProjectStructureUpdates()
  44. @owner.request.post {
  45. uri: "/Project/#{@example_project_id}/clone",
  46. json:
  47. projectName: 'new.tex'
  48. }, (error, res, body) =>
  49. throw error if error?
  50. if res.statusCode < 200 || res.statusCode >= 300
  51. throw new Error("failed to add doc #{res.statusCode}")
  52. @dup_project_id = body.project_id
  53. done()
  54. it "should version the docs created", ->
  55. updates = MockDocUpdaterApi.getProjectStructureUpdates(@dup_project_id).docUpdates
  56. expect(updates.length).to.equal(2)
  57. _.each updates, (update) =>
  58. expect(update.userId).to.equal(@owner._id)
  59. expect(update.docLines).to.be.a('string')
  60. expect(_.where(updates, pathname: "/main.tex").length).to.equal(1)
  61. expect(_.where(updates, pathname: "/references.bib").length).to.equal(1)
  62. it "should version the files created", ->
  63. updates = MockDocUpdaterApi.getProjectStructureUpdates(@dup_project_id).fileUpdates
  64. expect(updates.length).to.equal(1)
  65. update = updates[0]
  66. expect(update.userId).to.equal(@owner._id)
  67. expect(update.pathname).to.equal("/universe.jpg")
  68. expect(update.url).to.be.a('string');
  69. describe "adding a doc", ->
  70. before (done) ->
  71. MockDocUpdaterApi.clearProjectStructureUpdates()
  72. ProjectGetter.getProject @example_project_id, (error, projects) =>
  73. throw error if error?
  74. @owner.request.post {
  75. uri: "project/#{@example_project_id}/doc",
  76. json:
  77. name: 'new.tex'
  78. parent_folder_id: projects[0].rootFolder[0]._id
  79. }, (error, res, body) =>
  80. throw error if error?
  81. if res.statusCode < 200 || res.statusCode >= 300
  82. throw new Error("failed to add doc #{res.statusCode}")
  83. @example_doc_id = body._id
  84. done()
  85. it "should version the doc added", ->
  86. updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).docUpdates
  87. expect(updates.length).to.equal(1)
  88. update = updates[0]
  89. expect(update.userId).to.equal(@owner._id)
  90. expect(update.pathname).to.equal("/new.tex")
  91. expect(update.docLines).to.be.a('string');
  92. describe "uploading a project", ->
  93. before (done) ->
  94. MockDocUpdaterApi.clearProjectStructureUpdates()
  95. zip_file = fs.createReadStream(Path.resolve(__dirname + '/../files/test_project.zip'))
  96. req = @owner.request.post {
  97. uri: "project/new/upload",
  98. formData:
  99. qqfile: zip_file
  100. }, (error, res, body) =>
  101. throw error if error?
  102. if res.statusCode < 200 || res.statusCode >= 300
  103. throw new Error("failed to upload project #{res.statusCode}")
  104. @uploaded_project_id = JSON.parse(body).project_id
  105. done()
  106. it "should version the dosc created", ->
  107. updates = MockDocUpdaterApi.getProjectStructureUpdates(@uploaded_project_id).docUpdates
  108. expect(updates.length).to.equal(1)
  109. update = updates[0]
  110. expect(update.userId).to.equal(@owner._id)
  111. expect(update.pathname).to.equal("/main.tex")
  112. expect(update.docLines).to.equal("Test")
  113. it "should version the files created", ->
  114. updates = MockDocUpdaterApi.getProjectStructureUpdates(@uploaded_project_id).fileUpdates
  115. expect(updates.length).to.equal(1)
  116. update = updates[0]
  117. expect(update.userId).to.equal(@owner._id)
  118. expect(update.pathname).to.equal("/1pixel.png")
  119. expect(update.url).to.be.a('string');
  120. describe "uploading a file", ->
  121. before (done) ->
  122. ProjectGetter.getProject @example_project_id, (error, projects) =>
  123. throw error if error?
  124. @root_folder_id = projects[0].rootFolder[0]._id.toString()
  125. done()
  126. beforeEach () ->
  127. MockDocUpdaterApi.clearProjectStructureUpdates()
  128. it "should version a newly uploaded file", (done) ->
  129. image_file = fs.createReadStream(Path.resolve(__dirname + '/../files/1pixel.png'))
  130. req = @owner.request.post {
  131. uri: "project/#{@example_project_id}/upload",
  132. qs:
  133. folder_id: @root_folder_id
  134. formData:
  135. qqfile:
  136. value: image_file
  137. options:
  138. filename: '1pixel.png',
  139. contentType: 'image/png'
  140. }, (error, res, body) =>
  141. throw error if error?
  142. if res.statusCode < 200 || res.statusCode >= 300
  143. throw new Error("failed to upload file #{res.statusCode}")
  144. @example_file_id = JSON.parse(body).entity_id
  145. updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).fileUpdates
  146. expect(updates.length).to.equal(1)
  147. update = updates[0]
  148. expect(update.userId).to.equal(@owner._id)
  149. expect(update.pathname).to.equal("/1pixel.png")
  150. expect(update.url).to.be.a('string');
  151. @original_file_url = update.url
  152. done()
  153. it "should version a replacement file", (done) ->
  154. image_file = fs.createReadStream(Path.resolve(__dirname + '/../files/2pixel.png'))
  155. req = @owner.request.post {
  156. uri: "project/#{@example_project_id}/upload",
  157. qs:
  158. folder_id: @root_folder_id
  159. formData:
  160. qqfile:
  161. value: image_file
  162. options:
  163. filename: '1pixel.png',
  164. contentType: 'image/png'
  165. }, (error, res, body) =>
  166. throw error if error?
  167. if res.statusCode < 200 || res.statusCode >= 300
  168. throw new Error("failed to upload file #{res.statusCode}")
  169. updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).fileUpdates
  170. expect(updates.length).to.equal(1)
  171. update = updates[0]
  172. expect(update.userId).to.equal(@owner._id)
  173. expect(update.pathname).to.equal("/1pixel.png")
  174. expect(update.url).to.be.a('string');
  175. done()
  176. describe "moving entities", ->
  177. before (done) ->
  178. @owner.request.post {
  179. uri: "project/#{@example_project_id}/folder",
  180. formData:
  181. name: 'foo'
  182. }, (error, res, body) =>
  183. throw error if error?
  184. @example_folder_id_1 = JSON.parse(body)._id
  185. done()
  186. beforeEach () ->
  187. MockDocUpdaterApi.clearProjectStructureUpdates()
  188. it "should version moving a doc", (done) ->
  189. @owner.request.post {
  190. uri: "project/#{@example_project_id}/Doc/#{@example_doc_id}/move",
  191. json:
  192. folder_id: @example_folder_id_1
  193. }, (error, res, body) =>
  194. throw error if error?
  195. if res.statusCode < 200 || res.statusCode >= 300
  196. throw new Error("failed to move doc #{res.statusCode}")
  197. updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).docUpdates
  198. expect(updates.length).to.equal(1)
  199. update = updates[0]
  200. expect(update.userId).to.equal(@owner._id)
  201. expect(update.pathname).to.equal("/new.tex")
  202. expect(update.newPathname).to.equal("/foo/new.tex")
  203. done()
  204. it "should version moving a file", (done) ->
  205. @owner.request.post {
  206. uri: "project/#{@example_project_id}/File/#{@example_file_id}/move",
  207. json:
  208. folder_id: @example_folder_id_1
  209. }, (error, res, body) =>
  210. throw error if error?
  211. if res.statusCode < 200 || res.statusCode >= 300
  212. throw new Error("failed to move file #{res.statusCode}")
  213. updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).fileUpdates
  214. expect(updates.length).to.equal(1)
  215. update = updates[0]
  216. expect(update.userId).to.equal(@owner._id)
  217. expect(update.pathname).to.equal("/1pixel.png")
  218. expect(update.newPathname).to.equal("/foo/1pixel.png")
  219. done()
  220. it "should version moving a folder", (done) ->
  221. @owner.request.post {
  222. uri: "project/#{@example_project_id}/folder",
  223. formData:
  224. name: 'bar'
  225. }, (error, res, body) =>
  226. throw error if error?
  227. @example_folder_id_2 = JSON.parse(body)._id
  228. @owner.request.post {
  229. uri: "project/#{@example_project_id}/Folder/#{@example_folder_id_1}/move",
  230. json:
  231. folder_id: @example_folder_id_2
  232. }, (error, res, body) =>
  233. throw error if error?
  234. if res.statusCode < 200 || res.statusCode >= 300
  235. throw new Error("failed to move folder #{res.statusCode}")
  236. updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).docUpdates
  237. expect(updates.length).to.equal(1)
  238. update = updates[0]
  239. expect(update.userId).to.equal(@owner._id)
  240. expect(update.pathname).to.equal("/foo/new.tex")
  241. expect(update.newPathname).to.equal("/bar/foo/new.tex")
  242. updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).fileUpdates
  243. expect(updates.length).to.equal(1)
  244. update = updates[0]
  245. expect(update.userId).to.equal(@owner._id)
  246. expect(update.pathname).to.equal("/foo/1pixel.png")
  247. expect(update.newPathname).to.equal("/bar/foo/1pixel.png")
  248. done()
  249. describe "deleting entities", ->
  250. beforeEach () ->
  251. MockDocUpdaterApi.clearProjectStructureUpdates()
  252. it "should version deleting a folder", (done) ->
  253. @owner.request.delete {
  254. uri: "project/#{@example_project_id}/Folder/#{@example_folder_id_2}",
  255. }, (error, res, body) =>
  256. throw error if error?
  257. if res.statusCode < 200 || res.statusCode >= 300
  258. throw new Error("failed to delete folder #{res.statusCode}")
  259. updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).docUpdates
  260. expect(updates.length).to.equal(1)
  261. update = updates[0]
  262. expect(update.userId).to.equal(@owner._id)
  263. expect(update.pathname).to.equal("/bar/foo/new.tex")
  264. expect(update.newPathname).to.equal("")
  265. updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).fileUpdates
  266. expect(updates.length).to.equal(1)
  267. update = updates[0]
  268. expect(update.userId).to.equal(@owner._id)
  269. expect(update.pathname).to.equal("/bar/foo/1pixel.png")
  270. expect(update.newPathname).to.equal("")
  271. done()
  272. describe "tpds", ->
  273. before (done) ->
  274. @tpds_project_name = "tpds-project-#{new ObjectId().toString()}"
  275. @owner.createProject @tpds_project_name, (error, project_id) =>
  276. throw error if error?
  277. @tpds_project_id = project_id
  278. mkdirp Settings.path.dumpFolder, done
  279. beforeEach () ->
  280. MockDocUpdaterApi.clearProjectStructureUpdates()
  281. it "should version adding a doc", (done) ->
  282. tex_file = fs.createReadStream(Path.resolve(__dirname + '/../files/test.tex'))
  283. req = @owner.request.post {
  284. uri: "/user/#{@owner._id}/update/#{@tpds_project_name}/test.tex",
  285. auth:
  286. user: _.keys(Settings.httpAuthUsers)[0]
  287. pass: _.values(Settings.httpAuthUsers)[0]
  288. sendImmediately: true
  289. }
  290. tex_file.on "error", (err) ->
  291. throw err
  292. req.on "error", (err) ->
  293. throw err
  294. req.on "response", (res) =>
  295. if res.statusCode < 200 || res.statusCode >= 300
  296. throw new Error("failed to upload file #{res.statusCode}")
  297. updates = MockDocUpdaterApi.getProjectStructureUpdates(@tpds_project_id).docUpdates
  298. expect(updates.length).to.equal(1)
  299. update = updates[0]
  300. expect(update.userId).to.equal(@owner._id)
  301. expect(update.pathname).to.equal("/test.tex")
  302. expect(update.docLines).to.equal("Test")
  303. done()
  304. tex_file.pipe(req)
  305. it "should version adding a new file", (done) ->
  306. image_file = fs.createReadStream(Path.resolve(__dirname + '/../files/1pixel.png'))
  307. req = @owner.request.post {
  308. uri: "/user/#{@owner._id}/update/#{@tpds_project_name}/1pixel.png",
  309. auth:
  310. user: _.keys(Settings.httpAuthUsers)[0]
  311. pass: _.values(Settings.httpAuthUsers)[0]
  312. sendImmediately: true
  313. }
  314. image_file.on "error", (err) ->
  315. throw err
  316. req.on "error", (err) ->
  317. throw err
  318. req.on "response", (res) =>
  319. if res.statusCode < 200 || res.statusCode >= 300
  320. throw new Error("failed to upload file #{res.statusCode}")
  321. updates = MockDocUpdaterApi.getProjectStructureUpdates(@tpds_project_id).fileUpdates
  322. expect(updates.length).to.equal(1)
  323. update = updates[0]
  324. expect(update.userId).to.equal(@owner._id)
  325. expect(update.pathname).to.equal("/1pixel.png")
  326. expect(update.url).to.be.a('string');
  327. done()
  328. image_file.pipe(req)
  329. it "should version replacing a file", (done) ->
  330. image_file = fs.createReadStream(Path.resolve(__dirname + '/../files/2pixel.png'))
  331. req = @owner.request.post {
  332. uri: "/user/#{@owner._id}/update/#{@tpds_project_name}/1pixel.png",
  333. auth:
  334. user: _.keys(Settings.httpAuthUsers)[0]
  335. pass: _.values(Settings.httpAuthUsers)[0]
  336. sendImmediately: true
  337. }
  338. image_file.on "error", (err) ->
  339. throw err
  340. req.on "error", (err) ->
  341. throw err
  342. req.on "response", (res) =>
  343. if res.statusCode < 200 || res.statusCode >= 300
  344. throw new Error("failed to upload file #{res.statusCode}")
  345. updates = MockDocUpdaterApi.getProjectStructureUpdates(@tpds_project_id).fileUpdates
  346. expect(updates.length).to.equal(1)
  347. update = updates[0]
  348. expect(update.userId).to.equal(@owner._id)
  349. expect(update.pathname).to.equal("/1pixel.png")
  350. expect(update.url).to.be.a('string');
  351. done()
  352. image_file.pipe(req)
  353. it "should version deleting a doc", (done) ->
  354. req = @owner.request.delete {
  355. uri: "/user/#{@owner._id}/update/#{@tpds_project_name}/test.tex",
  356. auth:
  357. user: _.keys(Settings.httpAuthUsers)[0]
  358. pass: _.values(Settings.httpAuthUsers)[0]
  359. sendImmediately: true
  360. }, (error, res, body) =>
  361. throw error if error?
  362. if res.statusCode < 200 || res.statusCode >= 300
  363. throw new Error("failed to delete doc #{res.statusCode}")
  364. updates = MockDocUpdaterApi.getProjectStructureUpdates(@tpds_project_id).docUpdates
  365. expect(updates.length).to.equal(1)
  366. update = updates[0]
  367. expect(update.userId).to.equal(@owner._id)
  368. expect(update.pathname).to.equal("/test.tex")
  369. expect(update.newPathname).to.equal("")
  370. done()