diff --git a/services/document-updater/app/coffee/DocumentManager.coffee b/services/document-updater/app/coffee/DocumentManager.coffee index c557db3f54..8e69989d09 100644 --- a/services/document-updater/app/coffee/DocumentManager.coffee +++ b/services/document-updater/app/coffee/DocumentManager.coffee @@ -31,20 +31,20 @@ module.exports = DocumentManager = else callback null, lines, version, ranges, pathname, unflushedTime, true - getDocAndRecentOps: (project_id, doc_id, fromVersion, _callback = (error, lines, version, recentOps, ranges) ->) -> + getDocAndRecentOps: (project_id, doc_id, fromVersion, _callback = (error, lines, version, ops, ranges, pathname) ->) -> timer = new Metrics.Timer("docManager.getDocAndRecentOps") callback = (args...) -> timer.done() _callback(args...) - DocumentManager.getDoc project_id, doc_id, (error, lines, version, ranges) -> + DocumentManager.getDoc project_id, doc_id, (error, lines, version, ranges, pathname) -> return callback(error) if error? if fromVersion == -1 - callback null, lines, version, [], ranges + callback null, lines, version, [], ranges, pathname else RedisManager.getPreviousDocOps doc_id, fromVersion, version, (error, ops) -> return callback(error) if error? - callback null, lines, version, ops, ranges + callback null, lines, version, ops, ranges, pathname setDoc: (project_id, doc_id, newLines, source, user_id, undoing, _callback = (error) ->) -> timer = new Metrics.Timer("docManager.setDoc") @@ -179,7 +179,7 @@ module.exports = DocumentManager = UpdateManager = require "./UpdateManager" UpdateManager.lockUpdatesAndDo DocumentManager.getDoc, project_id, doc_id, callback - getDocAndRecentOpsWithLock: (project_id, doc_id, fromVersion, callback = (error, lines, version) ->) -> + getDocAndRecentOpsWithLock: (project_id, doc_id, fromVersion, callback = (error, lines, version, ops, ranges, pathname) ->) -> UpdateManager = require "./UpdateManager" UpdateManager.lockUpdatesAndDo DocumentManager.getDocAndRecentOps, project_id, doc_id, fromVersion, callback diff --git a/services/document-updater/app/coffee/HttpController.coffee b/services/document-updater/app/coffee/HttpController.coffee index 38e82fb04e..ef9f860552 100644 --- a/services/document-updater/app/coffee/HttpController.coffee +++ b/services/document-updater/app/coffee/HttpController.coffee @@ -18,7 +18,7 @@ module.exports = HttpController = else fromVersion = -1 - DocumentManager.getDocAndRecentOpsWithLock project_id, doc_id, fromVersion, (error, lines, version, ops, ranges) -> + DocumentManager.getDocAndRecentOpsWithLock project_id, doc_id, fromVersion, (error, lines, version, ops, ranges, pathname) -> timer.done() return next(error) if error? logger.log project_id: project_id, doc_id: doc_id, "got doc via http" @@ -30,6 +30,7 @@ module.exports = HttpController = version: version ops: ops ranges: ranges + pathname: pathname _getTotalSizeOfLines: (lines) -> size = 0 diff --git a/services/document-updater/test/acceptance/coffee/ApplyingUpdatesToProjectStructureTests.coffee b/services/document-updater/test/acceptance/coffee/ApplyingUpdatesToProjectStructureTests.coffee new file mode 100644 index 0000000000..21657793a8 --- /dev/null +++ b/services/document-updater/test/acceptance/coffee/ApplyingUpdatesToProjectStructureTests.coffee @@ -0,0 +1,98 @@ +sinon = require "sinon" +chai = require("chai") +chai.should() +Settings = require('settings-sharelatex') +rclient_history = require("redis-sharelatex").createClient(Settings.redis.history) +ProjectHistoryKeys = Settings.redis.project_history.key_schema + +MockWebApi = require "./helpers/MockWebApi" +DocUpdaterClient = require "./helpers/DocUpdaterClient" + +describe "Applying updates to a project's structure", -> + before -> + @user_id = 'user-id-123' + + describe "renaming a file", -> + before (done) -> + @project_id = DocUpdaterClient.randomId() + @fileUpdate = + id: DocUpdaterClient.randomId() + pathname: '/file-path' + newPathname: '/new-file-path' + @fileUpdates = [ @fileUpdate ] + DocUpdaterClient.sendProjectUpdate @project_id, @user_id, [], @fileUpdates, (error) -> + throw error if error? + setTimeout done, 200 + + it "should push the applied file renames to the project history changes api", (done) -> + rclient_history.lrange ProjectHistoryKeys.projectHistoryOps({@project_id}), 0, -1, (error, updates) => + throw error if error? + + update = JSON.parse(updates[0]) + update.file.should.equal @fileUpdate.id + update.pathname.should.equal '/file-path' + update.new_pathname.should.equal '/new-file-path' + update.meta.user_id.should.equal @user_id + update.meta.ts.should.be.a('string') + + done() + + describe "renaming a document", -> + before -> + @docUpdate = + id: DocUpdaterClient.randomId() + pathname: '/doc-path' + newPathname: '/new-doc-path' + @docUpdates = [ @docUpdate ] + + describe "when the document is not loaded", -> + before (done) -> + @project_id = DocUpdaterClient.randomId() + DocUpdaterClient.sendProjectUpdate @project_id, @user_id, @docUpdates, [], (error) -> + throw error if error? + setTimeout done, 200 + + it "should push the applied doc renames to the project history changes api", (done) -> + rclient_history.lrange ProjectHistoryKeys.projectHistoryOps({@project_id}), 0, -1, (error, updates) => + throw error if error? + + update = JSON.parse(updates[0]) + update.doc.should.equal @docUpdate.id + update.pathname.should.equal '/doc-path' + update.new_pathname.should.equal '/new-doc-path' + update.meta.user_id.should.equal @user_id + update.meta.ts.should.be.a('string') + + done() + + describe "when the document is loaded", -> + before (done) -> + @project_id = DocUpdaterClient.randomId() + MockWebApi.insertDoc @project_id, @docUpdate.id, {} + DocUpdaterClient.preloadDoc @project_id, @docUpdate.id, (error) => + throw error if error? + sinon.spy MockWebApi, "getDocument" + DocUpdaterClient.sendProjectUpdate @project_id, @user_id, @docUpdates, [], (error) -> + throw error if error? + setTimeout done, 200 + + after -> + MockWebApi.getDocument.restore() + + it "should update the doc", (done) -> + DocUpdaterClient.getDoc @project_id, @docUpdate.id, (error, res, doc) => + doc.pathname.should.equal @docUpdate.newPathname + done() + + it "should push the applied doc renames to the project history changes api", (done) -> + rclient_history.lrange ProjectHistoryKeys.projectHistoryOps({@project_id}), 0, -1, (error, updates) => + throw error if error? + + update = JSON.parse(updates[0]) + update.doc.should.equal @docUpdate.id + update.pathname.should.equal '/doc-path' + update.new_pathname.should.equal '/new-doc-path' + update.meta.user_id.should.equal @user_id + update.meta.ts.should.be.a('string') + + done() diff --git a/services/document-updater/test/acceptance/coffee/helpers/DocUpdaterClient.coffee b/services/document-updater/test/acceptance/coffee/helpers/DocUpdaterClient.coffee index 6b2a5ac2fb..f70271021b 100644 --- a/services/document-updater/test/acceptance/coffee/helpers/DocUpdaterClient.coffee +++ b/services/document-updater/test/acceptance/coffee/helpers/DocUpdaterClient.coffee @@ -86,3 +86,10 @@ module.exports = DocUpdaterClient = if body? and res.statusCode >= 200 and res.statusCode < 300 body = JSON.parse(body) callback error, res, body + + sendProjectUpdate: (project_id, userId, docUpdates, fileUpdates, callback = (error) ->) -> + request.post { + url: "http://localhost:3003/project/#{project_id}" + json: { userId, docUpdates, fileUpdates } + }, (error, res, body) -> + callback error, res, body diff --git a/services/document-updater/test/unit/coffee/DocumentManager/DocumentManagerTests.coffee b/services/document-updater/test/unit/coffee/DocumentManager/DocumentManagerTests.coffee index 6c7b051f7e..702617f7ae 100644 --- a/services/document-updater/test/unit/coffee/DocumentManager/DocumentManagerTests.coffee +++ b/services/document-updater/test/unit/coffee/DocumentManager/DocumentManagerTests.coffee @@ -109,7 +109,7 @@ describe "DocumentManager", -> describe "getDocAndRecentOps", -> describe "with a previous version specified", -> beforeEach -> - @DocumentManager.getDoc = sinon.stub().callsArgWith(2, null, @lines, @version, @ranges) + @DocumentManager.getDoc = sinon.stub().callsArgWith(2, null, @lines, @version, @ranges, @pathname) @RedisManager.getPreviousDocOps = sinon.stub().callsArgWith(3, null, @ops) @DocumentManager.getDocAndRecentOps @project_id, @doc_id, @fromVersion, @callback @@ -124,14 +124,14 @@ describe "DocumentManager", -> .should.equal true it "should call the callback with the doc info", -> - @callback.calledWith(null, @lines, @version, @ops, @ranges).should.equal true + @callback.calledWith(null, @lines, @version, @ops, @ranges, @pathname).should.equal true it "should time the execution", -> @Metrics.Timer::done.called.should.equal true describe "with no previous version specified", -> beforeEach -> - @DocumentManager.getDoc = sinon.stub().callsArgWith(2, null, @lines, @version, @ranges) + @DocumentManager.getDoc = sinon.stub().callsArgWith(2, null, @lines, @version, @ranges, @pathname) @RedisManager.getPreviousDocOps = sinon.stub().callsArgWith(3, null, @ops) @DocumentManager.getDocAndRecentOps @project_id, @doc_id, -1, @callback @@ -144,7 +144,7 @@ describe "DocumentManager", -> @RedisManager.getPreviousDocOps.called.should.equal false it "should call the callback with the doc info", -> - @callback.calledWith(null, @lines, @version, [], @ranges).should.equal true + @callback.calledWith(null, @lines, @version, [], @ranges, @pathname).should.equal true it "should time the execution", -> @Metrics.Timer::done.called.should.equal true diff --git a/services/document-updater/test/unit/coffee/HttpController/HttpControllerTests.coffee b/services/document-updater/test/unit/coffee/HttpController/HttpControllerTests.coffee index b5ebe02339..d52956635d 100644 --- a/services/document-updater/test/unit/coffee/HttpController/HttpControllerTests.coffee +++ b/services/document-updater/test/unit/coffee/HttpController/HttpControllerTests.coffee @@ -28,6 +28,7 @@ describe "HttpController", -> @version = 42 @fromVersion = 42 @ranges = { changes: "mock", comments: "mock" } + @pathname = '/a/b/c' @req = params: project_id: @project_id @@ -35,7 +36,7 @@ describe "HttpController", -> describe "when the document exists and no recent ops are requested", -> beforeEach -> - @DocumentManager.getDocAndRecentOpsWithLock = sinon.stub().callsArgWith(3, null, @lines, @version, [], @ranges) + @DocumentManager.getDocAndRecentOpsWithLock = sinon.stub().callsArgWith(3, null, @lines, @version, [], @ranges, @pathname) @HttpController.getDoc(@req, @res, @next) it "should get the doc", -> @@ -51,6 +52,7 @@ describe "HttpController", -> version: @version ops: [] ranges: @ranges + pathname: @pathname })) .should.equal true