updateProjectTests.coffee 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. sinon = require('sinon')
  2. chai = require('chai')
  3. should = chai.should()
  4. modulePath = "../../../../app/js/ProjectManager.js"
  5. SandboxedModule = require('sandboxed-module')
  6. _ = require('underscore')
  7. describe "ProjectManager", ->
  8. beforeEach ->
  9. @ProjectManager = SandboxedModule.require modulePath, requires:
  10. "./RedisManager": @RedisManager = {}
  11. "./ProjectHistoryRedisManager": @ProjectHistoryRedisManager = {}
  12. "./DocumentManager": @DocumentManager = {}
  13. "logger-sharelatex": @logger = { log: sinon.stub(), error: sinon.stub() }
  14. "./HistoryManager": @HistoryManager = {}
  15. "./Metrics": @Metrics =
  16. Timer: class Timer
  17. done: sinon.stub()
  18. @project_id = "project-id-123"
  19. @user_id = "user-id-123"
  20. @version = 1234567
  21. @HistoryManager.shouldFlushHistoryOps = sinon.stub().returns(false)
  22. @HistoryManager.flushProjectChangesAsync = sinon.stub()
  23. @callback = sinon.stub()
  24. describe "updateProjectWithLocks", ->
  25. describe "rename operations", ->
  26. beforeEach ->
  27. @firstDocUpdate =
  28. id: 1
  29. pathname: 'foo'
  30. newPathname: 'foo'
  31. @secondDocUpdate =
  32. id: 2
  33. pathname: 'bar'
  34. newPathname: 'bar2'
  35. @docUpdates = [ @firstDocUpdate, @secondDocUpdate ]
  36. @firstFileUpdate =
  37. id: 2
  38. pathname: 'bar'
  39. newPathname: 'bar2'
  40. @fileUpdates = [ @firstFileUpdate ]
  41. @DocumentManager.renameDocWithLock = sinon.stub().yields()
  42. @ProjectHistoryRedisManager.queueRenameEntity = sinon.stub().yields()
  43. describe "successfully", ->
  44. beforeEach ->
  45. @ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @version, @callback
  46. it "should rename the docs in the updates", ->
  47. firstDocUpdateWithVersion = _.extend({}, @firstDocUpdate, {version: "#{@version}.0"})
  48. secondDocUpdateWithVersion = _.extend({}, @secondDocUpdate, {version: "#{@version}.1"})
  49. @DocumentManager.renameDocWithLock
  50. .calledWith(@project_id, @firstDocUpdate.id, @user_id, firstDocUpdateWithVersion)
  51. .should.equal true
  52. @DocumentManager.renameDocWithLock
  53. .calledWith(@project_id, @secondDocUpdate.id, @user_id, secondDocUpdateWithVersion)
  54. .should.equal true
  55. it "should rename the files in the updates", ->
  56. firstFileUpdateWithVersion = _.extend({}, @firstFileUpdate, {version: "#{@version}.2"})
  57. @ProjectHistoryRedisManager.queueRenameEntity
  58. .calledWith(@project_id, 'file', @firstFileUpdate.id, @user_id, firstFileUpdateWithVersion)
  59. .should.equal true
  60. it "should not flush the history", ->
  61. @HistoryManager.flushProjectChangesAsync
  62. .calledWith(@project_id)
  63. .should.equal false
  64. it "should call the callback", ->
  65. @callback.called.should.equal true
  66. describe "when renaming a doc fails", ->
  67. beforeEach ->
  68. @error = new Error('error')
  69. @DocumentManager.renameDocWithLock = sinon.stub().yields(@error)
  70. @ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @version, @callback
  71. it "should call the callback with the error", ->
  72. @callback.calledWith(@error).should.equal true
  73. describe "when renaming a file fails", ->
  74. beforeEach ->
  75. @error = new Error('error')
  76. @ProjectHistoryRedisManager.queueRenameEntity = sinon.stub().yields(@error)
  77. @ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @version, @callback
  78. it "should call the callback with the error", ->
  79. @callback.calledWith(@error).should.equal true
  80. describe "with enough ops to flush", ->
  81. beforeEach ->
  82. @HistoryManager.shouldFlushHistoryOps = sinon.stub().returns(true)
  83. @ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @version, @callback
  84. it "should flush the history", ->
  85. @HistoryManager.flushProjectChangesAsync
  86. .calledWith(@project_id)
  87. .should.equal true
  88. describe "add operations", ->
  89. beforeEach ->
  90. @firstDocUpdate =
  91. id: 1
  92. docLines: "a\nb"
  93. @secondDocUpdate =
  94. id: 2
  95. docLines: "a\nb"
  96. @docUpdates = [ @firstDocUpdate, @secondDocUpdate ]
  97. @firstFileUpdate =
  98. id: 3
  99. url: 'filestore.example.com/2'
  100. @secondFileUpdate =
  101. id: 4
  102. url: 'filestore.example.com/3'
  103. @fileUpdates = [ @firstFileUpdate, @secondFileUpdate ]
  104. @ProjectHistoryRedisManager.queueAddEntity = sinon.stub().yields()
  105. describe "successfully", ->
  106. beforeEach ->
  107. @ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @version, @callback
  108. it "should add the docs in the updates", ->
  109. firstDocUpdateWithVersion = _.extend({}, @firstDocUpdate, {version: "#{@version}.0"})
  110. secondDocUpdateWithVersion = _.extend({}, @secondDocUpdate, {version: "#{@version}.1"})
  111. @ProjectHistoryRedisManager.queueAddEntity.getCall(0)
  112. .calledWith(@project_id, 'doc', @firstDocUpdate.id, @user_id, firstDocUpdateWithVersion)
  113. .should.equal true
  114. @ProjectHistoryRedisManager.queueAddEntity.getCall(1)
  115. .calledWith(@project_id, 'doc', @secondDocUpdate.id, @user_id, secondDocUpdateWithVersion)
  116. .should.equal true
  117. it "should add the files in the updates", ->
  118. firstFileUpdateWithVersion = _.extend({}, @firstFileUpdate, {version: "#{@version}.2"})
  119. secondFileUpdateWithVersion = _.extend({}, @secondFileUpdate, {version: "#{@version}.3"})
  120. @ProjectHistoryRedisManager.queueAddEntity.getCall(2)
  121. .calledWith(@project_id, 'file', @firstFileUpdate.id, @user_id, firstFileUpdateWithVersion)
  122. .should.equal true
  123. @ProjectHistoryRedisManager.queueAddEntity.getCall(3)
  124. .calledWith(@project_id, 'file', @secondFileUpdate.id, @user_id, secondFileUpdateWithVersion)
  125. .should.equal true
  126. it "should not flush the history", ->
  127. @HistoryManager.flushProjectChangesAsync
  128. .calledWith(@project_id)
  129. .should.equal false
  130. it "should call the callback", ->
  131. @callback.called.should.equal true
  132. describe "when adding a doc fails", ->
  133. beforeEach ->
  134. @error = new Error('error')
  135. @ProjectHistoryRedisManager.queueAddEntity = sinon.stub().yields(@error)
  136. @ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @version, @callback
  137. it "should call the callback with the error", ->
  138. @callback.calledWith(@error).should.equal true
  139. describe "when adding a file fails", ->
  140. beforeEach ->
  141. @error = new Error('error')
  142. @ProjectHistoryRedisManager.queueAddEntity = sinon.stub().yields(@error)
  143. @ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @version, @callback
  144. it "should call the callback with the error", ->
  145. @callback.calledWith(@error).should.equal true
  146. describe "with enough ops to flush", ->
  147. beforeEach ->
  148. @HistoryManager.shouldFlushHistoryOps = sinon.stub().returns(true)
  149. @ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @version, @callback
  150. it "should flush the history", ->
  151. @HistoryManager.flushProjectChangesAsync
  152. .calledWith(@project_id)
  153. .should.equal true