AppendingUpdatesTests.coffee 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. sinon = require "sinon"
  2. chai = require("chai")
  3. chai.should()
  4. expect = chai.expect
  5. mongojs = require "../../../app/js/mongojs"
  6. ObjectId = mongojs.ObjectId
  7. Settings = require "settings-sharelatex"
  8. request = require "request"
  9. rclient = require("redis").createClient() # Only works locally for now
  10. TrackChangesClient = require "./helpers/TrackChangesClient"
  11. MockWebApi = require "./helpers/MockWebApi"
  12. describe "Appending doc ops to the history", ->
  13. describe "when the history does not exist yet", ->
  14. before (done) ->
  15. @project_id = ObjectId().toString()
  16. @doc_id = ObjectId().toString()
  17. @user_id = ObjectId().toString()
  18. MockWebApi.projects[@project_id] = features: versioning: false
  19. TrackChangesClient.pushRawUpdates @project_id, @doc_id, [{
  20. op: [{ i: "f", p: 3 }]
  21. meta: { ts: Date.now(), user_id: @user_id }
  22. v: 3
  23. }, {
  24. op: [{ i: "o", p: 4 }]
  25. meta: { ts: Date.now(), user_id: @user_id }
  26. v: 4
  27. }, {
  28. op: [{ i: "o", p: 5 }]
  29. meta: { ts: Date.now(), user_id: @user_id }
  30. v: 5
  31. }], (error) =>
  32. throw error if error?
  33. TrackChangesClient.flushAndGetCompressedUpdates @project_id, @doc_id, (error, @updates) =>
  34. throw error if error?
  35. done()
  36. it "should insert the compressed op into mongo", ->
  37. expect(@updates[0].op).to.deep.equal [{
  38. p: 3, i: "foo"
  39. }]
  40. it "should insert the correct version number into mongo", ->
  41. expect(@updates[0].v).to.equal 5
  42. it "should store the doc id", ->
  43. expect(@updates[0].doc_id.toString()).to.equal @doc_id
  44. it "should store the project id", ->
  45. expect(@updates[0].project_id.toString()).to.equal @project_id
  46. it "should clear the doc from the DocsWithHistoryOps set", (done) ->
  47. rclient.sismember "DocsWithHistoryOps:#{@project_id}", @doc_id, (error, member) ->
  48. member.should.equal 0
  49. done()
  50. describe "when the history has already been started", ->
  51. beforeEach (done) ->
  52. @project_id = ObjectId().toString()
  53. @doc_id = ObjectId().toString()
  54. @user_id = ObjectId().toString()
  55. MockWebApi.projects[@project_id] = features: versioning: false
  56. TrackChangesClient.pushRawUpdates @project_id, @doc_id, [{
  57. op: [{ i: "f", p: 3 }]
  58. meta: { ts: Date.now(), user_id: @user_id }
  59. v: 3
  60. }, {
  61. op: [{ i: "o", p: 4 }]
  62. meta: { ts: Date.now(), user_id: @user_id }
  63. v: 4
  64. }, {
  65. op: [{ i: "o", p: 5 }]
  66. meta: { ts: Date.now(), user_id: @user_id }
  67. v: 5
  68. }], (error) =>
  69. throw error if error?
  70. TrackChangesClient.flushAndGetCompressedUpdates @project_id, @doc_id, (error, updates) =>
  71. throw error if error?
  72. done()
  73. describe "when the updates are recent and from the same user", ->
  74. beforeEach (done) ->
  75. TrackChangesClient.pushRawUpdates @project_id, @doc_id, [{
  76. op: [{ i: "b", p: 6 }]
  77. meta: { ts: Date.now(), user_id: @user_id }
  78. v: 6
  79. }, {
  80. op: [{ i: "a", p: 7 }]
  81. meta: { ts: Date.now(), user_id: @user_id }
  82. v: 7
  83. }, {
  84. op: [{ i: "r", p: 8 }]
  85. meta: { ts: Date.now(), user_id: @user_id }
  86. v: 8
  87. }], (error) =>
  88. throw error if error?
  89. TrackChangesClient.flushAndGetCompressedUpdates @project_id, @doc_id, (error, @updates) =>
  90. throw error if error?
  91. done()
  92. it "should combine all the updates into one", ->
  93. expect(@updates[0].op).to.deep.equal [{
  94. p: 3, i: "foobar"
  95. }]
  96. it "should insert the correct version number into mongo", ->
  97. expect(@updates[0].v).to.equal 8
  98. describe "when the updates are far apart", ->
  99. beforeEach (done) ->
  100. oneDay = 24 * 60 * 60 * 1000
  101. TrackChangesClient.pushRawUpdates @project_id, @doc_id, [{
  102. op: [{ i: "b", p: 6 }]
  103. meta: { ts: Date.now() + oneDay, user_id: @user_id }
  104. v: 6
  105. }, {
  106. op: [{ i: "a", p: 7 }]
  107. meta: { ts: Date.now() + oneDay, user_id: @user_id }
  108. v: 7
  109. }, {
  110. op: [{ i: "r", p: 8 }]
  111. meta: { ts: Date.now() + oneDay, user_id: @user_id }
  112. v: 8
  113. }], (error) =>
  114. throw error if error?
  115. TrackChangesClient.flushAndGetCompressedUpdates @project_id, @doc_id, (error, @updates) =>
  116. throw error if error?
  117. done()
  118. it "should keep the updates separate", ->
  119. expect(@updates[0].op).to.deep.equal [{
  120. p: 3, i: "foo"
  121. }]
  122. expect(@updates[1].op).to.deep.equal [{
  123. p: 6, i: "bar"
  124. }]
  125. describe "when the updates need processing in batches", ->
  126. before (done) ->
  127. @project_id = ObjectId().toString()
  128. @doc_id = ObjectId().toString()
  129. @user_id = ObjectId().toString()
  130. MockWebApi.projects[@project_id] = features: versioning: false
  131. updates = []
  132. @expectedOp = [{ p:0, i: "" }]
  133. for i in [0..250]
  134. updates.push {
  135. op: [{i: "a", p: 0}]
  136. meta: { ts: Date.now(), user_id: @user_id }
  137. v: i
  138. }
  139. @expectedOp[0].i = "a" + @expectedOp[0].i
  140. TrackChangesClient.pushRawUpdates @project_id, @doc_id, updates, (error) =>
  141. throw error if error?
  142. TrackChangesClient.flushAndGetCompressedUpdates @project_id, @doc_id, (error, @updates) =>
  143. throw error if error?
  144. done()
  145. it "should concat the compressed op into mongo", ->
  146. expect(@updates[0].op).to.deep.equal @expectedOp
  147. it "should insert the correct version number into mongo", ->
  148. expect(@updates[0].v).to.equal 250
  149. describe "when there are multiple ops in each update", ->
  150. before (done) ->
  151. @project_id = ObjectId().toString()
  152. @doc_id = ObjectId().toString()
  153. @user_id = ObjectId().toString()
  154. MockWebApi.projects[@project_id] = features: versioning: false
  155. oneDay = 24 * 60 * 60 * 1000
  156. TrackChangesClient.pushRawUpdates @project_id, @doc_id, [{
  157. op: [{ i: "f", p: 3 }, { i: "o", p: 4 }, { i: "o", p: 5 }]
  158. meta: { ts: Date.now(), user_id: @user_id }
  159. v: 3
  160. }, {
  161. op: [{ i: "b", p: 6 }, { i: "a", p: 7 }, { i: "r", p: 8 }]
  162. meta: { ts: Date.now() + oneDay, user_id: @user_id }
  163. v: 4
  164. }], (error) =>
  165. throw error if error?
  166. TrackChangesClient.flushAndGetCompressedUpdates @project_id, @doc_id, (error, @updates) =>
  167. throw error if error?
  168. done()
  169. it "should insert the compressed ops into mongo", ->
  170. expect(@updates[0].op).to.deep.equal [{
  171. p: 3, i: "foo"
  172. }]
  173. expect(@updates[1].op).to.deep.equal [{
  174. p: 6, i: "bar"
  175. }]
  176. it "should insert the correct version numbers into mongo", ->
  177. expect(@updates[0].v).to.equal 3
  178. expect(@updates[1].v).to.equal 4
  179. describe "when there is a no-op update", ->
  180. before (done) ->
  181. @project_id = ObjectId().toString()
  182. @doc_id = ObjectId().toString()
  183. @user_id = ObjectId().toString()
  184. MockWebApi.projects[@project_id] = features: versioning: false
  185. oneDay = 24 * 60 * 60 * 1000
  186. TrackChangesClient.pushRawUpdates @project_id, @doc_id, [{
  187. op: []
  188. meta: { ts: Date.now(), user_id: @user_id }
  189. v: 3
  190. }, {
  191. op: [{ i: "foo", p: 3 }]
  192. meta: { ts: Date.now() + oneDay, user_id: @user_id }
  193. v: 4
  194. }], (error) =>
  195. throw error if error?
  196. TrackChangesClient.flushAndGetCompressedUpdates @project_id, @doc_id, (error, @updates) =>
  197. throw error if error?
  198. done()
  199. it "should insert the compressed no-op into mongo", ->
  200. expect(@updates[0].op).to.deep.equal []
  201. it "should insert the compressed next update into mongo", ->
  202. expect(@updates[1].op).to.deep.equal [{
  203. p: 3, i: "foo"
  204. }]
  205. it "should insert the correct version numbers into mongo", ->
  206. expect(@updates[0].v).to.equal 3
  207. expect(@updates[1].v).to.equal 4
  208. describe "when the project has versioning enabled", ->
  209. before (done) ->
  210. @project_id = ObjectId().toString()
  211. @doc_id = ObjectId().toString()
  212. @user_id = ObjectId().toString()
  213. MockWebApi.projects[@project_id] = features: versioning: true
  214. TrackChangesClient.pushRawUpdates @project_id, @doc_id, [{
  215. op: [{ i: "f", p: 3 }]
  216. meta: { ts: Date.now(), user_id: @user_id }
  217. v: 3
  218. }], (error) =>
  219. throw error if error?
  220. TrackChangesClient.flushAndGetCompressedUpdates @project_id, @doc_id, (error, @updates) =>
  221. throw error if error?
  222. done()
  223. it "should not add a expiresAt entry in the update in mongo", ->
  224. expect(@updates[0].expiresAt).to.be.undefined
  225. describe "when the project does not have versioning enabled", ->
  226. before (done) ->
  227. @project_id = ObjectId().toString()
  228. @doc_id = ObjectId().toString()
  229. @user_id = ObjectId().toString()
  230. MockWebApi.projects[@project_id] = features: versioning: false
  231. TrackChangesClient.pushRawUpdates @project_id, @doc_id, [{
  232. op: [{ i: "f", p: 3 }]
  233. meta: { ts: Date.now(), user_id: @user_id }
  234. v: 3
  235. }], (error) =>
  236. throw error if error?
  237. TrackChangesClient.flushAndGetCompressedUpdates @project_id, @doc_id, (error, @updates) =>
  238. throw error if error?
  239. done()
  240. it "should add a expiresAt entry in the update in mongo", ->
  241. expect(@updates[0].expiresAt).to.exist