overleaf/services/document-updater/test/acceptance/coffee/RangesTests.js

373 lines
11 KiB
JavaScript
Raw Normal View History

2016-11-28 05:14:42 -05:00
sinon = require "sinon"
chai = require("chai")
chai.should()
expect = chai.expect
2016-11-28 05:14:42 -05:00
async = require "async"
{db, ObjectId} = require "../../../app/js/mongojs"
2016-11-28 05:14:42 -05:00
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
describe "Ranges", ->
before (done) ->
DocUpdaterApp.ensureRunning done
describe "tracking changes from ops", ->
2016-11-28 05:14:42 -05:00
before (done) ->
@project_id = DocUpdaterClient.randomId()
@user_id = DocUpdaterClient.randomId()
@id_seed = "587357bd35e64f6157"
2016-11-28 05:14:42 -05:00
@doc = {
id: DocUpdaterClient.randomId()
lines: ["aaa"]
2016-11-28 05:14:42 -05:00
}
@updates = [{
2016-11-28 05:14:42 -05:00
doc: @doc.id
op: [{ i: "123", p: 1 }]
2016-11-28 05:14:42 -05:00
v: 0
meta: { user_id: @user_id }
}, {
doc: @doc.id
op: [{ i: "456", p: 5 }]
v: 1
meta: { user_id: @user_id, tc: @id_seed }
}, {
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
}
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
it "should update the ranges", (done) ->
DocUpdaterClient.getDoc @project_id, @doc.id, (error, res, data) =>
2016-11-28 05:14:42 -05:00
throw error if error?
ranges = data.ranges
change = ranges.changes[0]
change.op.should.deep.equal { i: "456", p: 3 }
change.id.should.equal @id_seed + "000001"
2016-11-28 05:14:42 -05:00
change.metadata.user_id.should.equal @user_id
done()
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) =>
throw error if error?
async.series jobs, (error) ->
throw error if error?
setTimeout done, 200
it "should update the ranges", (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: 4, t: @tid }
2017-01-24 09:57:11 -05:00
comment.id.should.equal @tid
done()
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) =>
throw error if error?
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
describe "Loading ranges from persistence layer", ->
before (done) ->
@project_id = DocUpdaterClient.randomId()
@user_id = DocUpdaterClient.randomId()
@id_seed = "587357bd35e64f6157"
@doc = {
id: DocUpdaterClient.randomId()
lines: ["a123aa"]
}
@update = {
doc: @doc.id
op: [{ i: "456", p: 5 }]
v: 0
meta: { user_id: @user_id, tc: @id_seed }
}
MockWebApi.insertDoc @project_id, @doc.id, {
lines: @doc.lines
version: 0
ranges: {
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
it "should have preloaded the existing ranges", (done) ->
DocUpdaterClient.getDoc @project_id, @doc.id, (error, res, data) =>
throw error if error?
{changes} = data.ranges
changes[0].op.should.deep.equal { i: "123", p: 1 }
changes[1].op.should.deep.equal { i: "456", p: 5 }
done()
it "should flush the ranges to the persistence layer again", (done) ->
DocUpdaterClient.flushDoc @project_id, @doc.id, (error) =>
throw error if error?
MockWebApi.getDocument @project_id, @doc.id, (error, doc) =>
{changes} = doc.ranges
changes[0].op.should.deep.equal { i: "123", p: 1 }
changes[1].op.should.deep.equal { i: "456", p: 5 }
done()
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
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()
2019-04-16 06:05:17 -04:00
describe "deleting text surrounding a comment", ->
before (done) ->
@project_id = DocUpdaterClient.randomId()
@user_id = DocUpdaterClient.randomId()
@doc_id = DocUpdaterClient.randomId()
MockWebApi.insertDoc @project_id, @doc_id, {
lines: ["foo bar baz"]
version: 0
ranges: {
comments: [{
op: { c: "a", p: 5, tid: @tid = DocUpdaterClient.randomId() }
metadata:
user_id: @user_id
ts: new Date()
}]
}
}
@updates = [{
doc: @doc_id
op: [{ d: "foo ", p: 0 }]
v: 0
meta: { user_id: @user_id }
}, {
doc: @doc_id
op: [{ d: "bar ", p: 0 }]
v: 1
meta: { user_id: @user_id }
}]
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 () =>
DocUpdaterClient.getDoc @project_id, @doc_id, (error, res, data) =>
throw error if error?
done()
, 200
it "should write a snapshot from before the destructive change", (done) ->
DocUpdaterClient.getDoc @project_id, @doc_id, (error, res, data) =>
return done(error) if error?
db.docSnapshots.find {
project_id: ObjectId(@project_id),
doc_id: ObjectId(@doc_id)
}, (error, docSnapshots) =>
return done(error) if error?
expect(docSnapshots.length).to.equal 1
expect(docSnapshots[0].version).to.equal 1
expect(docSnapshots[0].lines).to.deep.equal ["bar baz"]
expect(docSnapshots[0].ranges.comments[0].op).to.deep.equal {
c: "a",
p: 1,
tid: @tid
}
done()