2016-11-28 05:14:42 -05:00
|
|
|
sinon = require "sinon"
|
|
|
|
chai = require("chai")
|
|
|
|
chai.should()
|
2017-01-09 08:41:18 -05:00
|
|
|
expect = chai.expect
|
2016-11-28 05:14:42 -05:00
|
|
|
async = require "async"
|
|
|
|
|
|
|
|
MockWebApi = require "./helpers/MockWebApi"
|
|
|
|
DocUpdaterClient = require "./helpers/DocUpdaterClient"
|
2018-02-15 11:28:40 -05:00
|
|
|
DocUpdaterApp = require "./helpers/DocUpdaterApp"
|
2016-11-28 05:14:42 -05:00
|
|
|
|
2016-12-08 07:31:43 -05:00
|
|
|
describe "Ranges", ->
|
|
|
|
describe "tracking changes from ops", ->
|
2016-11-28 05:14:42 -05:00
|
|
|
before (done) ->
|
|
|
|
@project_id = DocUpdaterClient.randomId()
|
2016-12-02 06:04:21 -05:00
|
|
|
@user_id = DocUpdaterClient.randomId()
|
2017-01-09 04:46:58 -05:00
|
|
|
@id_seed = "587357bd35e64f6157"
|
2016-11-28 05:14:42 -05:00
|
|
|
@doc = {
|
2016-12-02 06:04:21 -05:00
|
|
|
id: DocUpdaterClient.randomId()
|
|
|
|
lines: ["aaa"]
|
2016-11-28 05:14:42 -05:00
|
|
|
}
|
2016-12-02 06:04:21 -05:00
|
|
|
@updates = [{
|
2016-11-28 05:14:42 -05:00
|
|
|
doc: @doc.id
|
2016-12-02 06:04:21 -05:00
|
|
|
op: [{ i: "123", p: 1 }]
|
2016-11-28 05:14:42 -05:00
|
|
|
v: 0
|
2016-12-02 06:04:21 -05:00
|
|
|
meta: { user_id: @user_id }
|
|
|
|
}, {
|
|
|
|
doc: @doc.id
|
|
|
|
op: [{ i: "456", p: 5 }]
|
|
|
|
v: 1
|
2017-01-09 04:46:58 -05:00
|
|
|
meta: { user_id: @user_id, tc: @id_seed }
|
2016-12-02 06:04:21 -05:00
|
|
|
}, {
|
|
|
|
doc: @doc.id
|
|
|
|
op: [{ d: "12", p: 1 }]
|
|
|
|
v: 2
|
|
|
|
meta: { user_id: @user_id }
|
|
|
|
}]
|
2016-11-28 05:14:42 -05:00
|
|
|
MockWebApi.insertDoc @project_id, @doc.id, {
|
|
|
|
lines: @doc.lines
|
|
|
|
version: 0
|
|
|
|
}
|
2016-12-02 06:04:21 -05:00
|
|
|
jobs = []
|
|
|
|
for update in @updates
|
|
|
|
do (update) =>
|
|
|
|
jobs.push (callback) => DocUpdaterClient.sendUpdate @project_id, @doc.id, update, callback
|
2018-02-15 11:28:40 -05:00
|
|
|
|
|
|
|
DocUpdaterApp.ensureRunning (error) =>
|
2016-11-28 05:14:42 -05:00
|
|
|
throw error if error?
|
2018-02-15 11:28:40 -05:00
|
|
|
DocUpdaterClient.preloadDoc @project_id, @doc.id, (error) =>
|
2016-11-28 05:14:42 -05:00
|
|
|
throw error if error?
|
2018-02-15 11:28:40 -05:00
|
|
|
async.series jobs, (error) ->
|
|
|
|
throw error if error?
|
|
|
|
done()
|
2016-11-28 05:14:42 -05:00
|
|
|
|
2016-12-08 07:31:43 -05:00
|
|
|
it "should update the ranges", (done) ->
|
2016-12-02 06:37:27 -05:00
|
|
|
DocUpdaterClient.getDoc @project_id, @doc.id, (error, res, data) =>
|
2016-11-28 05:14:42 -05:00
|
|
|
throw error if error?
|
2016-12-08 07:31:43 -05:00
|
|
|
ranges = data.ranges
|
|
|
|
change = ranges.changes[0]
|
2016-12-02 06:04:21 -05:00
|
|
|
change.op.should.deep.equal { i: "456", p: 3 }
|
2017-01-09 04:46:58 -05:00
|
|
|
change.id.should.equal @id_seed + "000001"
|
2016-11-28 05:14:42 -05:00
|
|
|
change.metadata.user_id.should.equal @user_id
|
|
|
|
done()
|
2017-01-09 03:24:19 -05:00
|
|
|
|
|
|
|
describe "Adding comments", ->
|
|
|
|
describe "standalone", ->
|
|
|
|
before (done) ->
|
|
|
|
@project_id = DocUpdaterClient.randomId()
|
|
|
|
@user_id = DocUpdaterClient.randomId()
|
|
|
|
@doc = {
|
|
|
|
id: DocUpdaterClient.randomId()
|
|
|
|
lines: ["foo bar baz"]
|
|
|
|
}
|
|
|
|
@updates = [{
|
|
|
|
doc: @doc.id
|
|
|
|
op: [{ c: "bar", p: 4, t: @tid = DocUpdaterClient.randomId() }]
|
|
|
|
v: 0
|
|
|
|
}]
|
|
|
|
MockWebApi.insertDoc @project_id, @doc.id, {
|
|
|
|
lines: @doc.lines
|
|
|
|
version: 0
|
|
|
|
}
|
|
|
|
jobs = []
|
|
|
|
for update in @updates
|
|
|
|
do (update) =>
|
|
|
|
jobs.push (callback) => DocUpdaterClient.sendUpdate @project_id, @doc.id, update, callback
|
|
|
|
DocUpdaterClient.preloadDoc @project_id, @doc.id, (error) =>
|
2016-12-13 10:51:47 -05:00
|
|
|
throw error if error?
|
2017-01-09 03:24:19 -05:00
|
|
|
async.series jobs, (error) ->
|
2016-12-13 10:51:47 -05:00
|
|
|
throw error if error?
|
2017-01-09 03:24:19 -05:00
|
|
|
setTimeout done, 200
|
|
|
|
|
|
|
|
it "should update the ranges", (done) ->
|
|
|
|
DocUpdaterClient.getDoc @project_id, @doc.id, (error, res, data) =>
|
2016-12-13 10:51:47 -05:00
|
|
|
throw error if error?
|
2017-01-09 03:24:19 -05:00
|
|
|
ranges = data.ranges
|
|
|
|
comment = ranges.comments[0]
|
|
|
|
comment.op.should.deep.equal { c: "bar", p: 4, t: @tid }
|
2017-01-24 09:57:11 -05:00
|
|
|
comment.id.should.equal @tid
|
2017-01-09 03:24:19 -05:00
|
|
|
done()
|
2016-12-13 10:51:47 -05:00
|
|
|
|
2017-01-09 03:24:19 -05:00
|
|
|
describe "with conflicting ops needing OT", ->
|
|
|
|
before (done) ->
|
|
|
|
@project_id = DocUpdaterClient.randomId()
|
|
|
|
@user_id = DocUpdaterClient.randomId()
|
|
|
|
@doc = {
|
|
|
|
id: DocUpdaterClient.randomId()
|
|
|
|
lines: ["foo bar baz"]
|
|
|
|
}
|
|
|
|
@updates = [{
|
|
|
|
doc: @doc.id
|
|
|
|
op: [{ i: "ABC", p: 3 }]
|
|
|
|
v: 0
|
|
|
|
meta: { user_id: @user_id }
|
|
|
|
}, {
|
|
|
|
doc: @doc.id
|
|
|
|
op: [{ c: "bar", p: 4, t: @tid = DocUpdaterClient.randomId() }]
|
|
|
|
v: 0
|
|
|
|
}]
|
|
|
|
MockWebApi.insertDoc @project_id, @doc.id, {
|
|
|
|
lines: @doc.lines
|
|
|
|
version: 0
|
|
|
|
}
|
|
|
|
jobs = []
|
|
|
|
for update in @updates
|
|
|
|
do (update) =>
|
|
|
|
jobs.push (callback) => DocUpdaterClient.sendUpdate @project_id, @doc.id, update, callback
|
|
|
|
DocUpdaterClient.preloadDoc @project_id, @doc.id, (error) =>
|
2016-12-13 10:51:47 -05:00
|
|
|
throw error if error?
|
2017-01-09 03:24:19 -05:00
|
|
|
async.series jobs, (error) ->
|
|
|
|
throw error if error?
|
|
|
|
setTimeout done, 200
|
|
|
|
|
|
|
|
it "should update the comments with the OT shifted comment", (done) ->
|
|
|
|
DocUpdaterClient.getDoc @project_id, @doc.id, (error, res, data) =>
|
|
|
|
throw error if error?
|
|
|
|
ranges = data.ranges
|
|
|
|
comment = ranges.comments[0]
|
|
|
|
comment.op.should.deep.equal { c: "bar", p: 7, t: @tid }
|
|
|
|
done()
|
2016-11-28 05:14:42 -05:00
|
|
|
|
2016-12-08 07:31:43 -05:00
|
|
|
describe "Loading ranges from persistence layer", ->
|
2016-12-02 07:01:23 -05:00
|
|
|
before (done) ->
|
|
|
|
@project_id = DocUpdaterClient.randomId()
|
|
|
|
@user_id = DocUpdaterClient.randomId()
|
2017-01-09 04:46:58 -05:00
|
|
|
@id_seed = "587357bd35e64f6157"
|
2016-12-02 07:01:23 -05:00
|
|
|
@doc = {
|
|
|
|
id: DocUpdaterClient.randomId()
|
|
|
|
lines: ["a123aa"]
|
|
|
|
}
|
|
|
|
@update = {
|
|
|
|
doc: @doc.id
|
|
|
|
op: [{ i: "456", p: 5 }]
|
|
|
|
v: 0
|
2017-01-09 04:46:58 -05:00
|
|
|
meta: { user_id: @user_id, tc: @id_seed }
|
2016-12-02 07:01:23 -05:00
|
|
|
}
|
|
|
|
MockWebApi.insertDoc @project_id, @doc.id, {
|
|
|
|
lines: @doc.lines
|
|
|
|
version: 0
|
2016-12-08 07:31:43 -05:00
|
|
|
ranges: {
|
2016-12-02 07:01:23 -05:00
|
|
|
changes: [{
|
|
|
|
op: { i: "123", p: 1 }
|
|
|
|
metadata:
|
|
|
|
user_id: @user_id
|
|
|
|
ts: new Date()
|
|
|
|
}]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DocUpdaterClient.preloadDoc @project_id, @doc.id, (error) =>
|
|
|
|
throw error if error?
|
|
|
|
DocUpdaterClient.sendUpdate @project_id, @doc.id, @update, (error) ->
|
|
|
|
throw error if error?
|
|
|
|
setTimeout done, 200
|
|
|
|
|
2016-12-08 07:31:43 -05:00
|
|
|
it "should have preloaded the existing ranges", (done) ->
|
2016-12-02 07:01:23 -05:00
|
|
|
DocUpdaterClient.getDoc @project_id, @doc.id, (error, res, data) =>
|
|
|
|
throw error if error?
|
2016-12-08 07:31:43 -05:00
|
|
|
{changes} = data.ranges
|
2016-12-02 07:01:23 -05:00
|
|
|
changes[0].op.should.deep.equal { i: "123", p: 1 }
|
|
|
|
changes[1].op.should.deep.equal { i: "456", p: 5 }
|
|
|
|
done()
|
|
|
|
|
2016-12-08 07:31:43 -05:00
|
|
|
it "should flush the ranges to the persistence layer again", (done) ->
|
2016-12-02 07:01:23 -05:00
|
|
|
DocUpdaterClient.flushDoc @project_id, @doc.id, (error) =>
|
|
|
|
throw error if error?
|
|
|
|
MockWebApi.getDocument @project_id, @doc.id, (error, doc) =>
|
2016-12-08 07:31:43 -05:00
|
|
|
{changes} = doc.ranges
|
2016-12-02 07:01:23 -05:00
|
|
|
changes[0].op.should.deep.equal { i: "123", p: 1 }
|
|
|
|
changes[1].op.should.deep.equal { i: "456", p: 5 }
|
|
|
|
done()
|
2017-01-09 08:41:18 -05:00
|
|
|
|
|
|
|
describe "accepting a change", ->
|
|
|
|
before (done) ->
|
|
|
|
@project_id = DocUpdaterClient.randomId()
|
|
|
|
@user_id = DocUpdaterClient.randomId()
|
|
|
|
@id_seed = "587357bd35e64f6157"
|
|
|
|
@doc = {
|
|
|
|
id: DocUpdaterClient.randomId()
|
|
|
|
lines: ["aaa"]
|
|
|
|
}
|
|
|
|
@update = {
|
|
|
|
doc: @doc.id
|
|
|
|
op: [{ i: "456", p: 1 }]
|
|
|
|
v: 0
|
|
|
|
meta: { user_id: @user_id, tc: @id_seed }
|
|
|
|
}
|
|
|
|
MockWebApi.insertDoc @project_id, @doc.id, {
|
|
|
|
lines: @doc.lines
|
|
|
|
version: 0
|
|
|
|
}
|
|
|
|
DocUpdaterClient.preloadDoc @project_id, @doc.id, (error) =>
|
|
|
|
throw error if error?
|
|
|
|
DocUpdaterClient.sendUpdate @project_id, @doc.id, @update, (error) =>
|
|
|
|
throw error if error?
|
|
|
|
setTimeout () =>
|
|
|
|
DocUpdaterClient.getDoc @project_id, @doc.id, (error, res, data) =>
|
|
|
|
throw error if error?
|
|
|
|
ranges = data.ranges
|
|
|
|
change = ranges.changes[0]
|
|
|
|
change.op.should.deep.equal { i: "456", p: 1 }
|
|
|
|
change.id.should.equal @id_seed + "000001"
|
|
|
|
change.metadata.user_id.should.equal @user_id
|
|
|
|
done()
|
|
|
|
, 200
|
|
|
|
|
|
|
|
it "should remove the change after accepting", (done) ->
|
|
|
|
DocUpdaterClient.acceptChange @project_id, @doc.id, @id_seed + "000001", (error) =>
|
|
|
|
throw error if error?
|
|
|
|
DocUpdaterClient.getDoc @project_id, @doc.id, (error, res, data) =>
|
|
|
|
throw error if error?
|
|
|
|
expect(data.ranges.changes).to.be.undefined
|
2017-01-24 09:57:11 -05:00
|
|
|
done()
|
|
|
|
|
|
|
|
describe "deleting a comment range", ->
|
|
|
|
before (done) ->
|
|
|
|
@project_id = DocUpdaterClient.randomId()
|
|
|
|
@user_id = DocUpdaterClient.randomId()
|
|
|
|
@doc = {
|
|
|
|
id: DocUpdaterClient.randomId()
|
|
|
|
lines: ["foo bar"]
|
|
|
|
}
|
|
|
|
@update = {
|
|
|
|
doc: @doc.id
|
|
|
|
op: [{ c: "bar", p: 4, t: @tid = DocUpdaterClient.randomId() }]
|
|
|
|
v: 0
|
|
|
|
}
|
|
|
|
MockWebApi.insertDoc @project_id, @doc.id, {
|
|
|
|
lines: @doc.lines
|
|
|
|
version: 0
|
|
|
|
}
|
|
|
|
DocUpdaterClient.preloadDoc @project_id, @doc.id, (error) =>
|
|
|
|
throw error if error?
|
|
|
|
DocUpdaterClient.sendUpdate @project_id, @doc.id, @update, (error) =>
|
|
|
|
throw error if error?
|
|
|
|
setTimeout () =>
|
|
|
|
DocUpdaterClient.getDoc @project_id, @doc.id, (error, res, data) =>
|
|
|
|
throw error if error?
|
|
|
|
ranges = data.ranges
|
|
|
|
change = ranges.comments[0]
|
|
|
|
change.op.should.deep.equal { c: "bar", p: 4, t: @tid }
|
|
|
|
change.id.should.equal @tid
|
|
|
|
done()
|
|
|
|
, 200
|
|
|
|
|
|
|
|
it "should remove the comment range", (done) ->
|
|
|
|
DocUpdaterClient.removeComment @project_id, @doc.id, @tid, (error, res) =>
|
|
|
|
throw error if error?
|
|
|
|
expect(res.statusCode).to.equal 204
|
|
|
|
DocUpdaterClient.getDoc @project_id, @doc.id, (error, res, data) =>
|
|
|
|
throw error if error?
|
|
|
|
expect(data.ranges.comments).to.be.undefined
|
2017-02-27 08:34:20 -05:00
|
|
|
done()
|
|
|
|
|
|
|
|
describe "tripping range size limit", ->
|
|
|
|
before (done) ->
|
|
|
|
@project_id = DocUpdaterClient.randomId()
|
|
|
|
@user_id = DocUpdaterClient.randomId()
|
|
|
|
@id_seed = DocUpdaterClient.randomId()
|
|
|
|
@doc = {
|
|
|
|
id: DocUpdaterClient.randomId()
|
|
|
|
lines: ["aaa"]
|
|
|
|
}
|
|
|
|
@i = new Array(3 * 1024 * 1024).join("a")
|
|
|
|
@updates = [{
|
|
|
|
doc: @doc.id
|
|
|
|
op: [{ i: @i, p: 1 }]
|
|
|
|
v: 0
|
|
|
|
meta: { user_id: @user_id, tc: @id_seed }
|
|
|
|
}]
|
|
|
|
MockWebApi.insertDoc @project_id, @doc.id, {
|
|
|
|
lines: @doc.lines
|
|
|
|
version: 0
|
|
|
|
}
|
|
|
|
jobs = []
|
|
|
|
for update in @updates
|
|
|
|
do (update) =>
|
|
|
|
jobs.push (callback) => DocUpdaterClient.sendUpdate @project_id, @doc.id, update, callback
|
|
|
|
DocUpdaterClient.preloadDoc @project_id, @doc.id, (error) =>
|
|
|
|
throw error if error?
|
|
|
|
async.series jobs, (error) ->
|
|
|
|
throw error if error?
|
|
|
|
setTimeout done, 200
|
|
|
|
|
|
|
|
it "should not update the ranges", (done) ->
|
|
|
|
DocUpdaterClient.getDoc @project_id, @doc.id, (error, res, data) =>
|
|
|
|
throw error if error?
|
|
|
|
ranges = data.ranges
|
|
|
|
expect(ranges.changes).to.be.undefined
|
|
|
|
done()
|