mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Create DiffManager.getDiff
This commit is contained in:
parent
1d1dcdfa2f
commit
8b71d222d4
4 changed files with 184 additions and 27 deletions
|
@ -1,8 +1,35 @@
|
|||
HistoryManager = require "./HistoryManager"
|
||||
DocumentUpdaterManager = require "./DocumentUpdaterManager"
|
||||
MongoManager = require "./MongoManager"
|
||||
DiffGenerator = require "./DiffGenerator"
|
||||
|
||||
module.exports = DiffManager =
|
||||
getDiff: (doc_id, fromDate, toDate, callback = (error, diff) ->) ->
|
||||
# Flush diff
|
||||
# Get doc content and version
|
||||
# Get updates from Mongo
|
||||
# Check version matches
|
||||
# Build diff
|
||||
# Return diff
|
||||
getLatestDocAndUpdates: (project_id, doc_id, fromDate, toDate, callback = (error, lines, version, updates) ->) ->
|
||||
HistoryManager.processUncompressedUpdatesWithLock doc_id, (error) ->
|
||||
return callback(error) if error?
|
||||
DocumentUpdaterManager.getDocument project_id, doc_id, (error, lines, version) ->
|
||||
return callback(error) if error?
|
||||
MongoManager.getUpdatesBetweenDates doc_id, fromDate, toDate, (error, updates) ->
|
||||
return callback(error) if error?
|
||||
callback(null, lines, version, updates)
|
||||
|
||||
getDiff: (project_id, doc_id, fromDate, toDate, callback = (error, diff) ->) ->
|
||||
DiffManager.getLatestDocAndUpdates project_id, doc_id, fromDate, null, (error, lines, version, updates) ->
|
||||
return callback(error) if error?
|
||||
lastUpdate = updates[updates.length - 1]
|
||||
if lastUpdate? and lastUpdate.v != version
|
||||
return callback new Error("latest update version, #{lastUpdate.v}, does not match doc version, #{version}")
|
||||
|
||||
|
||||
updatesToApply = []
|
||||
for update in updates
|
||||
if update.meta.end_ts <= toDate
|
||||
updatesToApply.push update
|
||||
|
||||
try
|
||||
startingContent = DiffGenerator.rewindUpdates lines.join("\n"), updates
|
||||
diff = DiffGenerator.buildDiff startingContent, updatesToApply
|
||||
catch e
|
||||
return callback(e)
|
||||
|
||||
callback(null, diff)
|
|
@ -40,12 +40,14 @@ module.exports = MongoManager =
|
|||
}, callback
|
||||
|
||||
getUpdatesBetweenDates:(doc_id, fromDate, toDate, callback = (error, updates) ->) ->
|
||||
query =
|
||||
doc_id: ObjectId(doc_id.toString())
|
||||
if fromDate?
|
||||
query["meta.start_ts"] = { $gte: fromDate }
|
||||
if toDate?
|
||||
query["meta.end_ts"] = { $lte: toDate }
|
||||
db.docHistory
|
||||
.find({
|
||||
doc_id: ObjectId(doc_id.toString())
|
||||
"meta.start_ts" : { $gte: fromDate }
|
||||
"meta.end_ts" : { $lte: toDate }
|
||||
})
|
||||
.find( query )
|
||||
.sort( "meta.end_ts": -1 )
|
||||
.toArray callback
|
||||
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
sinon = require('sinon')
|
||||
chai = require('chai')
|
||||
should = chai.should()
|
||||
expect = chai.expect
|
||||
modulePath = "../../../../app/js/DiffManager.js"
|
||||
SandboxedModule = require('sandboxed-module')
|
||||
|
||||
describe "DiffManager", ->
|
||||
beforeEach ->
|
||||
@DiffManager = SandboxedModule.require modulePath, requires:
|
||||
"logger-sharelatex": @logger = { log: sinon.stub(), error: sinon.stub() }
|
||||
"./HistoryManager": @HistoryManager = {}
|
||||
"./DocumentUpdaterManager": @DocumentUpdaterManager = {}
|
||||
"./MongoManager": @MongoManager = {}
|
||||
"./DiffGenerator": @DiffGenerator = {}
|
||||
@callback = sinon.stub()
|
||||
@from = new Date()
|
||||
@to = new Date(Date.now() + 10000)
|
||||
@project_id = "mock-project-id"
|
||||
@doc_id = "mock-doc-id"
|
||||
|
||||
describe "getLatestDocAndUpdates", ->
|
||||
beforeEach ->
|
||||
@lines = [ "hello", "world" ]
|
||||
@version = 42
|
||||
@updates = [ "mock-update-1", "mock-update-2" ]
|
||||
|
||||
@HistoryManager.processUncompressedUpdatesWithLock = sinon.stub().callsArg(1)
|
||||
@DocumentUpdaterManager.getDocument = sinon.stub().callsArgWith(2, null, @lines, @version)
|
||||
@MongoManager.getUpdatesBetweenDates = sinon.stub().callsArgWith(3, null, @updates)
|
||||
@DiffManager.getLatestDocAndUpdates @project_id, @doc_id, @from, @to, @callback
|
||||
|
||||
it "should ensure the latest updates have been compressed", ->
|
||||
@HistoryManager.processUncompressedUpdatesWithLock
|
||||
.calledWith(@doc_id)
|
||||
.should.equal true
|
||||
|
||||
it "should get the latest version of the doc", ->
|
||||
@DocumentUpdaterManager.getDocument
|
||||
.calledWith(@project_id, @doc_id)
|
||||
.should.equal true
|
||||
|
||||
it "should get the requested updates from Mongo", ->
|
||||
@MongoManager.getUpdatesBetweenDates
|
||||
.calledWith(@doc_id, @from, @to)
|
||||
.should.equal true
|
||||
|
||||
it "should call the callback with the lines, version and updates", ->
|
||||
@callback.calledWith(null, @lines, @version, @updates).should.equal true
|
||||
|
||||
describe "getDiff", ->
|
||||
beforeEach ->
|
||||
@lines = [ "hello", "world" ]
|
||||
@version = 42
|
||||
@updates = [
|
||||
{ op: "mock-1", v: 41, meta: { end_ts: new Date(@to.getTime() - 10)} }
|
||||
{ op: "mock-2", v: 42, meta: { end_ts: new Date(@to.getTime() + 10)} }
|
||||
]
|
||||
@diffed_updates = @updates.slice(0,1)
|
||||
@rewound_content = "rewound-content"
|
||||
@diff = [ u: "mock-diff" ]
|
||||
|
||||
describe "with matching versions", ->
|
||||
beforeEach ->
|
||||
@DiffManager.getLatestDocAndUpdates = sinon.stub().callsArgWith(4, null, @lines, @version, @updates)
|
||||
@DiffGenerator.rewindUpdates = sinon.stub().returns(@rewound_content)
|
||||
@DiffGenerator.buildDiff = sinon.stub().returns(@diff)
|
||||
@DiffManager.getDiff @project_id, @doc_id, @from, @to, @callback
|
||||
|
||||
it "should get the latest doc and version with all recent updates", ->
|
||||
@DiffManager.getLatestDocAndUpdates
|
||||
.calledWith(@project_id, @doc_id, @from, null)
|
||||
.should.equal true
|
||||
|
||||
it "should rewind the diff", ->
|
||||
@DiffGenerator.rewindUpdates
|
||||
.calledWith(@lines.join("\n"), @updates)
|
||||
.should.equal true
|
||||
|
||||
it "should generate the diff", ->
|
||||
@DiffGenerator.buildDiff
|
||||
.calledWith(@rewound_content, @diffed_updates)
|
||||
.should.equal true
|
||||
|
||||
it "should call the callback with the diff", ->
|
||||
@callback.calledWith(null, @diff).should.equal true
|
||||
|
||||
describe "with mismatching versions", ->
|
||||
beforeEach ->
|
||||
@version = 42
|
||||
@updates = [ { op: "mock-1", v: 39 }, { op: "mock-1", v: 40 } ]
|
||||
@DiffManager.getLatestDocAndUpdates = sinon.stub().callsArgWith(4, null, @lines, @version, @updates)
|
||||
@DiffManager.getDiff @project_id, @doc_id, @from, @to, @callback
|
||||
|
||||
it "should call the callback with an error", ->
|
||||
@callback
|
||||
.calledWith(new Error("latest update version, 40, does not match doc version, 42"))
|
||||
.should.equal true
|
||||
|
||||
describe "when the updates are inconsistent", ->
|
||||
beforeEach ->
|
||||
@DiffManager.getLatestDocAndUpdates = sinon.stub().callsArgWith(4, null, @lines, @version, @updates)
|
||||
@DiffGenerator.rewindUpdates = sinon.stub().throws(@error = new Error("inconsistent!"))
|
||||
@DiffManager.getDiff @project_id, @doc_id, @from, @to, @callback
|
||||
|
||||
it "should call the callback with an error", ->
|
||||
@callback
|
||||
.calledWith(@error)
|
||||
.should.equal true
|
||||
|
|
@ -143,21 +143,39 @@ describe "MongoManager", ->
|
|||
@from = new Date(Date.now())
|
||||
@to = new Date(Date.now() + 100000)
|
||||
|
||||
@MongoManager.getUpdatesBetweenDates @doc_id, @from, @to, @callback
|
||||
describe "with a toDate", ->
|
||||
beforeEach ->
|
||||
@MongoManager.getUpdatesBetweenDates @doc_id, @from, @to, @callback
|
||||
|
||||
it "should find the updates for the doc", ->
|
||||
@db.docHistory.find
|
||||
.calledWith({
|
||||
doc_id: ObjectId(@doc_id)
|
||||
"meta.start_ts": { $gte: @from }
|
||||
"meta.end_ts": { $lte: @to }
|
||||
})
|
||||
.should.equal true
|
||||
it "should find the all updates between the to and from date", ->
|
||||
@db.docHistory.find
|
||||
.calledWith({
|
||||
doc_id: ObjectId(@doc_id)
|
||||
"meta.start_ts": { $gte: @from }
|
||||
"meta.end_ts": { $lte: @to }
|
||||
})
|
||||
.should.equal true
|
||||
|
||||
it "should sort in descending timestamp order", ->
|
||||
@db.docHistory.sort
|
||||
.calledWith("meta.end_ts": -1)
|
||||
.should.equal true
|
||||
it "should sort in descending timestamp order", ->
|
||||
@db.docHistory.sort
|
||||
.calledWith("meta.end_ts": -1)
|
||||
.should.equal true
|
||||
|
||||
it "should call the call back with the updates", ->
|
||||
@callback.calledWith(null, @updates).should.equal true
|
||||
|
||||
describe "without a todo date", ->
|
||||
beforeEach ->
|
||||
@MongoManager.getUpdatesBetweenDates @doc_id, @from, null, @callback
|
||||
|
||||
it "should find the all updates after the from date", ->
|
||||
@db.docHistory.find
|
||||
.calledWith({
|
||||
doc_id: ObjectId(@doc_id)
|
||||
"meta.start_ts": { $gte: @from }
|
||||
})
|
||||
.should.equal true
|
||||
|
||||
it "should call the call back with the updates", ->
|
||||
@callback.calledWith(null, @updates).should.equal true
|
||||
|
||||
it "should call the call back with the updates", ->
|
||||
@callback.calledWith(null, @updates).should.equal true
|
||||
|
|
Loading…
Reference in a new issue