ApplyingUpdatesToProjectStructureTests.coffee 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. sinon = require "sinon"
  2. chai = require("chai")
  3. chai.should()
  4. Settings = require('settings-sharelatex')
  5. rclient_history = require("redis-sharelatex").createClient(Settings.redis.history)
  6. ProjectHistoryKeys = Settings.redis.project_history.key_schema
  7. MockProjectHistoryApi = require "./helpers/MockProjectHistoryApi"
  8. MockWebApi = require "./helpers/MockWebApi"
  9. DocUpdaterClient = require "./helpers/DocUpdaterClient"
  10. DocUpdaterApp = require "./helpers/DocUpdaterApp"
  11. describe "Applying updates to a project's structure", ->
  12. before ->
  13. @user_id = 'user-id-123'
  14. @version = 1234
  15. describe "renaming a file", ->
  16. before (done) ->
  17. @project_id = DocUpdaterClient.randomId()
  18. @fileUpdate =
  19. id: DocUpdaterClient.randomId()
  20. pathname: '/file-path'
  21. newPathname: '/new-file-path'
  22. @fileUpdates = [ @fileUpdate ]
  23. DocUpdaterApp.ensureRunning (error) =>
  24. throw error if error?
  25. DocUpdaterClient.sendProjectUpdate @project_id, @user_id, [], @fileUpdates, @version, (error) ->
  26. throw error if error?
  27. setTimeout done, 200
  28. it "should push the applied file renames to the project history api", (done) ->
  29. rclient_history.lrange ProjectHistoryKeys.projectHistoryOps({@project_id}), 0, -1, (error, updates) =>
  30. throw error if error?
  31. update = JSON.parse(updates[0])
  32. update.file.should.equal @fileUpdate.id
  33. update.pathname.should.equal '/file-path'
  34. update.new_pathname.should.equal '/new-file-path'
  35. update.meta.user_id.should.equal @user_id
  36. update.meta.ts.should.be.a('string')
  37. update.version.should.equal "#{@version}.0"
  38. done()
  39. describe "renaming a document", ->
  40. before ->
  41. @docUpdate =
  42. id: DocUpdaterClient.randomId()
  43. pathname: '/doc-path'
  44. newPathname: '/new-doc-path'
  45. @docUpdates = [ @docUpdate ]
  46. describe "when the document is not loaded", ->
  47. before (done) ->
  48. @project_id = DocUpdaterClient.randomId()
  49. DocUpdaterClient.sendProjectUpdate @project_id, @user_id, @docUpdates, [], @version, (error) ->
  50. throw error if error?
  51. setTimeout done, 200
  52. it "should push the applied doc renames to the project history api", (done) ->
  53. rclient_history.lrange ProjectHistoryKeys.projectHistoryOps({@project_id}), 0, -1, (error, updates) =>
  54. throw error if error?
  55. update = JSON.parse(updates[0])
  56. update.doc.should.equal @docUpdate.id
  57. update.pathname.should.equal '/doc-path'
  58. update.new_pathname.should.equal '/new-doc-path'
  59. update.meta.user_id.should.equal @user_id
  60. update.meta.ts.should.be.a('string')
  61. update.version.should.equal "#{@version}.0"
  62. done()
  63. describe "when the document is loaded", ->
  64. before (done) ->
  65. @project_id = DocUpdaterClient.randomId()
  66. MockWebApi.insertDoc @project_id, @docUpdate.id, {}
  67. DocUpdaterClient.preloadDoc @project_id, @docUpdate.id, (error) =>
  68. throw error if error?
  69. sinon.spy MockWebApi, "getDocument"
  70. DocUpdaterClient.sendProjectUpdate @project_id, @user_id, @docUpdates, [], @version, (error) ->
  71. throw error if error?
  72. setTimeout done, 200
  73. after ->
  74. MockWebApi.getDocument.restore()
  75. it "should update the doc", (done) ->
  76. DocUpdaterClient.getDoc @project_id, @docUpdate.id, (error, res, doc) =>
  77. doc.pathname.should.equal @docUpdate.newPathname
  78. done()
  79. it "should push the applied doc renames to the project history api", (done) ->
  80. rclient_history.lrange ProjectHistoryKeys.projectHistoryOps({@project_id}), 0, -1, (error, updates) =>
  81. throw error if error?
  82. update = JSON.parse(updates[0])
  83. update.doc.should.equal @docUpdate.id
  84. update.pathname.should.equal '/doc-path'
  85. update.new_pathname.should.equal '/new-doc-path'
  86. update.meta.user_id.should.equal @user_id
  87. update.meta.ts.should.be.a('string')
  88. update.version.should.equal "#{@version}.0"
  89. done()
  90. describe "adding a file", ->
  91. before (done) ->
  92. @project_id = DocUpdaterClient.randomId()
  93. @fileUpdate =
  94. id: DocUpdaterClient.randomId()
  95. pathname: '/file-path'
  96. url: 'filestore.example.com'
  97. @fileUpdates = [ @fileUpdate ]
  98. DocUpdaterClient.sendProjectUpdate @project_id, @user_id, [], @fileUpdates, @version, (error) ->
  99. throw error if error?
  100. setTimeout done, 200
  101. it "should push the file addition to the project history api", (done) ->
  102. rclient_history.lrange ProjectHistoryKeys.projectHistoryOps({@project_id}), 0, -1, (error, updates) =>
  103. throw error if error?
  104. update = JSON.parse(updates[0])
  105. update.file.should.equal @fileUpdate.id
  106. update.pathname.should.equal '/file-path'
  107. update.url.should.equal 'filestore.example.com'
  108. update.meta.user_id.should.equal @user_id
  109. update.meta.ts.should.be.a('string')
  110. update.version.should.equal "#{@version}.0"
  111. done()
  112. describe "adding a doc", ->
  113. before (done) ->
  114. @project_id = DocUpdaterClient.randomId()
  115. @docUpdate =
  116. id: DocUpdaterClient.randomId()
  117. pathname: '/file-path'
  118. docLines: 'a\nb'
  119. @docUpdates = [ @docUpdate ]
  120. DocUpdaterClient.sendProjectUpdate @project_id, @user_id, @docUpdates, [], @version, (error) ->
  121. throw error if error?
  122. setTimeout done, 200
  123. it "should push the doc addition to the project history api", (done) ->
  124. rclient_history.lrange ProjectHistoryKeys.projectHistoryOps({@project_id}), 0, -1, (error, updates) =>
  125. throw error if error?
  126. update = JSON.parse(updates[0])
  127. update.doc.should.equal @docUpdate.id
  128. update.pathname.should.equal '/file-path'
  129. update.docLines.should.equal 'a\nb'
  130. update.meta.user_id.should.equal @user_id
  131. update.meta.ts.should.be.a('string')
  132. update.version.should.equal "#{@version}.0"
  133. done()
  134. describe "with enough updates to flush to the history service", ->
  135. before (done) ->
  136. @project_id = DocUpdaterClient.randomId()
  137. @user_id = DocUpdaterClient.randomId()
  138. @version0 = 12345
  139. @version1 = @version0 + 1
  140. updates = []
  141. for v in [0..599] # Should flush after 500 ops
  142. updates.push
  143. id: DocUpdaterClient.randomId(),
  144. pathname: '/file-' + v
  145. docLines: 'a\nb'
  146. sinon.spy MockProjectHistoryApi, "flushProject"
  147. # Send updates in chunks to causes multiple flushes
  148. projectId = @project_id
  149. userId = @project_id
  150. DocUpdaterClient.sendProjectUpdate projectId, userId, updates.slice(0, 250), [], @version0, (error) ->
  151. throw error if error?
  152. DocUpdaterClient.sendProjectUpdate projectId, userId, updates.slice(250), [], @version1, (error) ->
  153. throw error if error?
  154. setTimeout done, 2000
  155. after ->
  156. MockProjectHistoryApi.flushProject.restore()
  157. it "should flush project history", ->
  158. MockProjectHistoryApi.flushProject.calledWith(@project_id).should.equal true
  159. describe "with too few updates to flush to the history service", ->
  160. before (done) ->
  161. @project_id = DocUpdaterClient.randomId()
  162. @user_id = DocUpdaterClient.randomId()
  163. @version0 = 12345
  164. @version1 = @version0 + 1
  165. updates = []
  166. for v in [0..42] # Should flush after 500 ops
  167. updates.push
  168. id: DocUpdaterClient.randomId(),
  169. pathname: '/file-' + v
  170. docLines: 'a\nb'
  171. sinon.spy MockProjectHistoryApi, "flushProject"
  172. # Send updates in chunks
  173. projectId = @project_id
  174. userId = @project_id
  175. DocUpdaterClient.sendProjectUpdate projectId, userId, updates.slice(0, 10), [], @version0, (error) ->
  176. throw error if error?
  177. DocUpdaterClient.sendProjectUpdate projectId, userId, updates.slice(10), [], @version1, (error) ->
  178. throw error if error?
  179. setTimeout done, 2000
  180. after ->
  181. MockProjectHistoryApi.flushProject.restore()
  182. it "should not flush project history", ->
  183. MockProjectHistoryApi.flushProject.calledWith(@project_id).should.equal false