diff --git a/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee b/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee index f7dd9f3e17..bbd7ca4919 100644 --- a/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee +++ b/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee @@ -207,8 +207,8 @@ module.exports = DocumentUpdaterHandler = updateProjectStructure : (project_id, userId, changes, callback = (error) ->)-> return callback() if !settings.apis.project_history?.enabled - docUpdates = DocumentUpdaterHandler._getRenameUpdates('doc', changes.oldDocs, changes.newDocs) - fileUpdates = DocumentUpdaterHandler._getRenameUpdates('file', changes.oldFiles, changes.newFiles) + docUpdates = DocumentUpdaterHandler._getUpdates('doc', changes.oldDocs, changes.newDocs) + fileUpdates = DocumentUpdaterHandler._getUpdates('file', changes.oldFiles, changes.newFiles) timer = new metrics.Timer("set-document") url = "#{settings.apis.documentupdater.url}/project/#{project_id}" @@ -230,7 +230,7 @@ module.exports = DocumentUpdaterHandler = logger.error {project_id, url}, "doc updater returned a non-success status code: #{res.statusCode}" callback new Error("doc updater returned a non-success status code: #{res.statusCode}") - _getRenameUpdates: (entityType, oldEntities, newEntities) -> + _getUpdates: (entityType, oldEntities, newEntities) -> oldEntities ||= [] newEntities ||= [] updates = [] @@ -255,6 +255,16 @@ module.exports = DocumentUpdaterHandler = pathname: oldEntity.path newPathname: newEntity.path + for id, oldEntity of oldEntitiesHash + newEntity = newEntitiesHash[id] + + if !newEntity? + # entity deleted + updates.push + id: id + pathname: oldEntity.path + newPathname: '' + updates PENDINGUPDATESKEY = "PendingUpdates" diff --git a/services/web/app/coffee/Features/Editor/EditorController.coffee b/services/web/app/coffee/Features/Editor/EditorController.coffee index f66094f9e8..532f515a10 100644 --- a/services/web/app/coffee/Features/Editor/EditorController.coffee +++ b/services/web/app/coffee/Features/Editor/EditorController.coffee @@ -105,19 +105,19 @@ module.exports = EditorController = async.series jobs, (err)-> callback err, newFolders, lastFolder - deleteEntity : (project_id, entity_id, entityType, source, callback)-> + deleteEntity : (project_id, entity_id, entityType, source, userId, callback)-> LockManager.getLock project_id, (err)-> if err? logger.err err:err, project_id:project_id, "could not get lock to deleteEntity" return callback(err) - EditorController.deleteEntityWithoutLock project_id, entity_id, entityType, source, (err)-> + EditorController.deleteEntityWithoutLock project_id, entity_id, entityType, source, userId, (err)-> LockManager.releaseLock project_id, ()-> callback(err) - deleteEntityWithoutLock: (project_id, entity_id, entityType, source, callback)-> + deleteEntityWithoutLock: (project_id, entity_id, entityType, source, userId, callback)-> logger.log {project_id, entity_id, entityType, source}, "start delete process of entity" Metrics.inc "editor.delete-entity" - ProjectEntityHandler.deleteEntity project_id, entity_id, entityType, (err)-> + ProjectEntityHandler.deleteEntity project_id, entity_id, entityType, userId, (err)-> if err? logger.err err:err, project_id:project_id, entity_id:entity_id, entityType:entityType, "error deleting entity" return callback(err) diff --git a/services/web/app/coffee/Features/Editor/EditorHttpController.coffee b/services/web/app/coffee/Features/Editor/EditorHttpController.coffee index cbc296b69f..16b1a79e31 100644 --- a/services/web/app/coffee/Features/Editor/EditorHttpController.coffee +++ b/services/web/app/coffee/Features/Editor/EditorHttpController.coffee @@ -147,6 +147,7 @@ module.exports = EditorHttpController = project_id = req.params.Project_id entity_id = req.params.entity_id entity_type = req.params.entity_type - EditorController.deleteEntity project_id, entity_id, entity_type, "editor", (error) -> + user_id = AuthenticationController.getLoggedInUserId(req) + EditorController.deleteEntity project_id, entity_id, entity_type, "editor", user_id, (error) -> return next(error) if error? res.sendStatus 204 diff --git a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee index 446786fa57..a9d7c708ee 100644 --- a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee @@ -412,7 +412,7 @@ module.exports = ProjectEntityHandler = callback() - deleteEntity: (project_id, entity_id, entityType, callback = (error) ->)-> + deleteEntity: (project_id, entity_id, entityType, userId, callback = (error) ->)-> self = @ logger.log entity_id:entity_id, entityType:entityType, project_id:project_id, "deleting project entity" if !entityType? @@ -423,7 +423,7 @@ module.exports = ProjectEntityHandler = return callback(error) if error? projectLocator.findElement {project: project, element_id: entity_id, type: entityType}, (error, entity, path)=> return callback(error) if error? - ProjectEntityHandler._cleanUpEntity project, entity, entityType, (error) -> + ProjectEntityHandler._cleanUpEntity project, entity, entityType, path.fileSystem, userId, (error) -> return callback(error) if error? tpdsUpdateSender.deleteEntity project_id:project_id, path:path.fileSystem, project_name:project.name, (error) -> return callback(error) if error? @@ -456,17 +456,17 @@ module.exports = ProjectEntityHandler = return callback(error) if error? DocumentUpdaterHandler.updateProjectStructure project_id, userId, {oldDocs, newDocs, oldFiles, newFiles}, callback - _cleanUpEntity: (project, entity, entityType, callback = (error) ->) -> + _cleanUpEntity: (project, entity, entityType, path, userId, callback = (error) ->) -> if(entityType.indexOf("file") != -1) - ProjectEntityHandler._cleanUpFile project, entity, callback + ProjectEntityHandler._cleanUpFile project, entity, path, userId, callback else if (entityType.indexOf("doc") != -1) - ProjectEntityHandler._cleanUpDoc project, entity, callback + ProjectEntityHandler._cleanUpDoc project, entity, path, userId, callback else if (entityType.indexOf("folder") != -1) - ProjectEntityHandler._cleanUpFolder project, entity, callback + ProjectEntityHandler._cleanUpFolder project, entity, path, userId, callback else callback() - _cleanUpDoc: (project, doc, callback = (error) ->) -> + _cleanUpDoc: (project, doc, path, userId, callback = (error) ->) -> project_id = project._id.toString() doc_id = doc._id.toString() unsetRootDocIfRequired = (callback) => @@ -483,26 +483,33 @@ module.exports = ProjectEntityHandler = return callback(error) if error? DocstoreManager.deleteDoc project_id, doc_id, (error) -> return callback(error) if error? - callback() + changes = oldDocs: [ {doc, path} ] + DocumentUpdaterHandler.updateProjectStructure project_id, userId, changes, callback - _cleanUpFile: (project, file, callback = (error) ->) -> + _cleanUpFile: (project, file, path, userId, callback = (error) ->) -> project_id = project._id.toString() file_id = file._id.toString() - FileStoreHandler.deleteFile project_id, file_id, callback + FileStoreHandler.deleteFile project_id, file_id, (error) -> + return callback(error) if error? + changes = oldFiles: [ {file, path} ] + DocumentUpdaterHandler.updateProjectStructure project_id, userId, changes, callback - _cleanUpFolder: (project, folder, callback = (error) ->) -> + _cleanUpFolder: (project, folder, folderPath, userId, callback = (error) ->) -> jobs = [] for doc in folder.docs do (doc) -> - jobs.push (callback) -> ProjectEntityHandler._cleanUpDoc project, doc, callback + docPath = path.join(folderPath, doc.name) + jobs.push (callback) -> ProjectEntityHandler._cleanUpDoc project, doc, docPath, userId, callback for file in folder.fileRefs do (file) -> - jobs.push (callback) -> ProjectEntityHandler._cleanUpFile project, file, callback + filePath = path.join(folderPath, file.name) + jobs.push (callback) -> ProjectEntityHandler._cleanUpFile project, file, filePath, userId, callback for childFolder in folder.folders do (childFolder) -> - jobs.push (callback) -> ProjectEntityHandler._cleanUpFolder project, childFolder, callback + folderPath = path.join(folderPath, childFolder.name) + jobs.push (callback) -> ProjectEntityHandler._cleanUpFolder project, childFolder, folderPath, userId, callback async.series jobs, callback diff --git a/services/web/app/coffee/Features/ThirdPartyDataStore/TpdsUpdateHandler.coffee b/services/web/app/coffee/Features/ThirdPartyDataStore/TpdsUpdateHandler.coffee index c78b588e8a..78e3f12ed6 100644 --- a/services/web/app/coffee/Features/ThirdPartyDataStore/TpdsUpdateHandler.coffee +++ b/services/web/app/coffee/Features/ThirdPartyDataStore/TpdsUpdateHandler.coffee @@ -47,7 +47,7 @@ module.exports = logger.log user_id:user_id, filePath:path, projectName:projectName, project_id:project._id, "project found for delete update, path is root so marking project as deleted" return projectDeleter.markAsDeletedByExternalSource project._id, callback else - updateMerger.deleteUpdate project._id, path, source, (err)-> + updateMerger.deleteUpdate user_id, project._id, path, source, (err)-> callback(err) diff --git a/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee b/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee index 010594d16a..e49c52aab2 100644 --- a/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee +++ b/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee @@ -32,13 +32,13 @@ module.exports = else self.p.processDoc project_id, elementId, user_id, fsPath, path, source, callback - deleteUpdate: (project_id, path, source, callback)-> + deleteUpdate: (user_id, project_id, path, source, callback)-> projectLocator.findElementByPath project_id, path, (err, element, type)-> if err? || !element? logger.log element:element, project_id:project_id, path:path, "could not find entity for deleting, assuming it was already deleted" return callback() logger.log project_id:project_id, path:path, type:type, element:element, "processing update to delete entity from tpds" - editorController.deleteEntity project_id, element._id, type, source, (err)-> + editorController.deleteEntity project_id, element._id, type, source, user_id, (err)-> logger.log project_id:project_id, path:path, "finished processing update to delete entity from tpds" callback() diff --git a/services/web/test/acceptance/coffee/ProjectStructureTests.coffee b/services/web/test/acceptance/coffee/ProjectStructureTests.coffee index e54d4fac9d..cb59efe1df 100644 --- a/services/web/test/acceptance/coffee/ProjectStructureTests.coffee +++ b/services/web/test/acceptance/coffee/ProjectStructureTests.coffee @@ -91,6 +91,7 @@ describe "ProjectStructureChanges", -> throw error if error? if res.statusCode < 200 || res.statusCode >= 300 throw new Error("failed to add doc #{res.statusCode}") + @example_doc_id = body._id done() it "should version the doc added", -> @@ -162,6 +163,8 @@ describe "ProjectStructureChanges", -> if res.statusCode < 200 || res.statusCode >= 300 throw new Error("failed to upload file #{res.statusCode}") + @example_file_id = JSON.parse(body).entity_id + updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).fileUpdates expect(updates.length).to.equal(1) update = updates[0] @@ -199,6 +202,120 @@ describe "ProjectStructureChanges", -> done() + describe "moving entities", -> + before (done) -> + @owner.request.post { + uri: "project/#{@example_project_id}/folder", + formData: + name: 'foo' + }, (error, res, body) => + throw error if error? + @example_folder_id_1 = JSON.parse(body)._id + done() + + beforeEach () -> + MockDocUpdaterApi.clearProjectStructureUpdates() + + it "should version moving a doc", (done) -> + @owner.request.post { + uri: "project/#{@example_project_id}/Doc/#{@example_doc_id}/move", + json: + folder_id: @example_folder_id_1 + }, (error, res, body) => + throw error if error? + if res.statusCode < 200 || res.statusCode >= 300 + throw new Error("failed to move doc #{res.statusCode}") + + updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).docUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/new.tex") + expect(update.newPathname).to.equal("/foo/new.tex") + + done() + + it "should version moving a file", (done) -> + @owner.request.post { + uri: "project/#{@example_project_id}/File/#{@example_file_id}/move", + json: + folder_id: @example_folder_id_1 + }, (error, res, body) => + throw error if error? + if res.statusCode < 200 || res.statusCode >= 300 + throw new Error("failed to move file #{res.statusCode}") + + updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).fileUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/1pixel.png") + expect(update.newPathname).to.equal("/foo/1pixel.png") + + done() + + it "should version moving a folder", (done) -> + @owner.request.post { + uri: "project/#{@example_project_id}/folder", + formData: + name: 'bar' + }, (error, res, body) => + throw error if error? + @example_folder_id_2 = JSON.parse(body)._id + + @owner.request.post { + uri: "project/#{@example_project_id}/Folder/#{@example_folder_id_1}/move", + json: + folder_id: @example_folder_id_2 + }, (error, res, body) => + throw error if error? + if res.statusCode < 200 || res.statusCode >= 300 + throw new Error("failed to move folder #{res.statusCode}") + + updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).docUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/foo/new.tex") + expect(update.newPathname).to.equal("/bar/foo/new.tex") + + updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).fileUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/foo/1pixel.png") + expect(update.newPathname).to.equal("/bar/foo/1pixel.png") + + done() + + describe "deleting entities", -> + beforeEach () -> + MockDocUpdaterApi.clearProjectStructureUpdates() + + it "should version deleting a folder", (done) -> + @owner.request.delete { + uri: "project/#{@example_project_id}/Folder/#{@example_folder_id_2}", + }, (error, res, body) => + throw error if error? + if res.statusCode < 200 || res.statusCode >= 300 + throw new Error("failed to delete folder #{res.statusCode}") + + updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).docUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/bar/foo/new.tex") + expect(update.newPathname).to.equal("") + + updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).fileUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/bar/foo/1pixel.png") + expect(update.newPathname).to.equal("") + + done() + describe "tpds", -> before (done) -> @tpds_project_name = "tpds-project-#{new ObjectId().toString()}" @@ -305,3 +422,25 @@ describe "ProjectStructureChanges", -> done() image_file.pipe(req) + + it "should version deleting a doc", (done) -> + req = @owner.request.delete { + uri: "/user/#{@owner._id}/update/#{@tpds_project_name}/test.tex", + auth: + user: _.keys(Settings.httpAuthUsers)[0] + pass: _.values(Settings.httpAuthUsers)[0] + sendImmediately: true + }, (error, res, body) => + throw error if error? + if res.statusCode < 200 || res.statusCode >= 300 + throw new Error("failed to delete doc #{res.statusCode}") + + updates = MockDocUpdaterApi.getProjectStructureUpdates(@tpds_project_id).docUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/test.tex") + expect(update.newPathname).to.equal("") + + done() + diff --git a/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee b/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee index b00cd6b173..b21fb1adab 100644 --- a/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee +++ b/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee @@ -33,6 +33,9 @@ module.exports = MockDocUpdaterApi = @addProjectStructureUpdates(project_id, userId, docUpdates, fileUpdates) res.sendStatus 200 + app.delete "/project/:project_id/doc/:doc_id", (req, res, next) => + res.send 204 + app.listen 3003, (error) -> throw error if error? .on "error", (error) -> diff --git a/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee b/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee index c5b003ac75..631538fd89 100644 --- a/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee +++ b/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee @@ -23,6 +23,16 @@ module.exports = MockDocStoreApi = docs = (doc for doc_id, doc of @docs[req.params.project_id]) res.send JSON.stringify docs + app.delete "/project/:project_id/doc/:doc_id", (req, res, next) => + {project_id, doc_id} = req.params + if !@docs[project_id]? + res.send 404 + else if !@docs[project_id][doc_id]? + res.send 404 + else + @docs[project_id][doc_id] = undefined + res.send 204 + app.listen 3016, (error) -> throw error if error? .on "error", (error) -> diff --git a/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee b/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee index 14ccaa3a33..111d2ace68 100644 --- a/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee +++ b/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee @@ -478,14 +478,22 @@ describe 'DocumentUpdaterHandler', -> .should.equal true done() - describe "when a doc has been deleted", -> - it 'should do nothing', (done) -> + describe "when an entity has been deleted", -> + it 'should end the structure update to the document updater', (done) -> @docId = new ObjectId() @changes = oldDocs: [ { path: '/foo', docLines: 'a\nb', doc: _id: @docId } ] + docUpdates = [ + id: @docId.toString(), + pathname: '/foo', + newPathname: '' + ] + @handler.updateProjectStructure @project_id, @user_id, @changes, () => - @request.post.called.should.equal false + @request.post + .calledWith(url: @url, json: {docUpdates, fileUpdates: [], userId: @user_id}) + .should.equal true done() diff --git a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee index 4e1af79b46..85760f510d 100644 --- a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee +++ b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee @@ -376,58 +376,53 @@ describe "EditorController", -> err.should.equal "timed out" done() - describe "deleteEntity", -> - beforeEach -> @LockManager.getLock.callsArgWith(1) @LockManager.releaseLock.callsArgWith(1) - @EditorController.deleteEntityWithoutLock = sinon.stub().callsArgWith(4) + @EditorController.deleteEntityWithoutLock = sinon.stub().callsArgWith(5) it "should call deleteEntityWithoutLock", (done)-> - @EditorController.deleteEntity @project_id, @entity_id, @type, @source, => - @EditorController.deleteEntityWithoutLock.calledWith(@project_id, @entity_id, @type, @source).should.equal true + @EditorController.deleteEntity @project_id, @entity_id, @type, @source, @user_id, => + @EditorController.deleteEntityWithoutLock + .calledWith(@project_id, @entity_id, @type, @source, @user_id) + .should.equal true done() it "should take the lock", (done)-> - @EditorController.deleteEntity @project_id, @entity_id, @type, @source, => + @EditorController.deleteEntity @project_id, @entity_id, @type, @source, @user_id, => @LockManager.getLock.calledWith(@project_id).should.equal true done() it "should release the lock", (done)-> - @EditorController.deleteEntity @project_id, @entity_id, @type, @source, (error)=> + @EditorController.deleteEntity @project_id, @entity_id, @type, @source, @user_id, (error) => @LockManager.releaseLock.calledWith(@project_id).should.equal true done() it "should error if it can't cat the lock", (done)-> @LockManager.getLock = sinon.stub().callsArgWith(1, "timed out") - @EditorController.deleteEntity @project_id, @entity_id, @type, @source, (err)=> - expect(err).to.exist - err.should.equal "timed out" - done() - - + @EditorController.deleteEntity @project_id, @entity_id, @type, @source, @user_id, (error) => + expect(error).to.exist + error.should.equal "timed out" + done() describe 'deleteEntityWithoutLock', -> - beforeEach -> - @ProjectEntityHandler.deleteEntity = (project_id, entity_id, type, callback)-> callback() + beforeEach (done) -> @entity_id = "entity_id_here" @type = "doc" @EditorRealTimeController.emitToRoom = sinon.stub() + @ProjectEntityHandler.deleteEntity = sinon.stub().callsArg(4) + @EditorController.deleteEntityWithoutLock @project_id, @entity_id, @type, @source, @user_id, done - it 'should delete the folder using the project entity handler', (done)-> - mock = sinon.mock(@ProjectEntityHandler).expects("deleteEntity").withArgs(@project_id, @entity_id, @type).callsArg(3) + it 'should delete the folder using the project entity handler', -> + @ProjectEntityHandler.deleteEntity + .calledWith(@project_id, @entity_id, @type, @user_id) + .should.equal.true - @EditorController.deleteEntityWithoutLock @project_id, @entity_id, @type, @source, -> - mock.verify() - done() - - it 'notify users an entity has been deleted', (done)-> - @EditorController.deleteEntityWithoutLock @project_id, @entity_id, @type, @source, => - @EditorRealTimeController.emitToRoom - .calledWith(@project_id, "removeEntity", @entity_id, @source) - .should.equal true - done() + it 'notify users an entity has been deleted', -> + @EditorRealTimeController.emitToRoom + .calledWith(@project_id, "removeEntity", @entity_id, @source) + .should.equal true describe "getting a list of project paths", -> diff --git a/services/web/test/unit/coffee/Editor/EditorHttpControllerTests.coffee b/services/web/test/unit/coffee/Editor/EditorHttpControllerTests.coffee index e05846c5d5..38419e6b46 100644 --- a/services/web/test/unit/coffee/Editor/EditorHttpControllerTests.coffee +++ b/services/web/test/unit/coffee/Editor/EditorHttpControllerTests.coffee @@ -331,12 +331,12 @@ describe "EditorHttpController", -> Project_id: @project_id entity_id: @entity_id = "entity-id-123" entity_type: @entity_type = "entity-type" - @EditorController.deleteEntity = sinon.stub().callsArg(4) + @EditorController.deleteEntity = sinon.stub().callsArg(5) @EditorHttpController.deleteEntity @req, @res it "should call EditorController.deleteEntity", -> @EditorController.deleteEntity - .calledWith(@project_id, @entity_id, @entity_type, "editor") + .calledWith(@project_id, @entity_id, @entity_type, "editor", @userId) .should.equal true it "should send back a success response", -> diff --git a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee index f62690e226..7c4188052f 100644 --- a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee @@ -157,13 +157,13 @@ describe 'ProjectEntityHandler', -> @ProjectGetter.getProject.callsArgWith(2, null, @project) @tpdsUpdateSender.deleteEntity = sinon.stub().callsArg(1) @ProjectEntityHandler._removeElementFromMongoArray = sinon.stub().callsArg(3) - @ProjectEntityHandler._cleanUpEntity = sinon.stub().callsArg(3) + @ProjectEntityHandler._cleanUpEntity = sinon.stub().callsArg(5) @path = mongo: "mongo.path", fileSystem: "/file/system/path" @projectLocator.findElement = sinon.stub().callsArgWith(1, null, @entity = { _id: entity_id }, @path) describe "deleting from Mongo", -> beforeEach (done) -> - @ProjectEntityHandler.deleteEntity project_id, entity_id, @type = 'file', done + @ProjectEntityHandler.deleteEntity project_id, entity_id, @type = 'file', userId, done it "should retreive the path", -> @projectLocator.findElement.called.should.equal true @@ -182,7 +182,7 @@ describe 'ProjectEntityHandler', -> it "should clean up the entity from the rest of the system", -> @ProjectEntityHandler._cleanUpEntity - .calledWith(@project, @entity, @type) + .calledWith(@project, @entity, @type, @path.fileSystem, userId) .should.equal true describe "_cleanUpEntity", -> @@ -193,7 +193,9 @@ describe 'ProjectEntityHandler', -> describe "a file", -> beforeEach (done) -> - @ProjectEntityHandler._cleanUpEntity @project, _id: @entity_id, 'file', done + @path = "/file/system/path.png" + @entity = _id: @entity_id + @ProjectEntityHandler._cleanUpEntity @project, @entity, 'file', @path, userId, done it "should delete the file from FileStoreHandler", -> @FileStoreHandler.deleteFile.calledWith(project_id, @entity_id).should.equal true @@ -201,38 +203,56 @@ describe 'ProjectEntityHandler', -> it "should not attempt to delete from the document updater", -> @documentUpdaterHandler.deleteDoc.called.should.equal false + it "should should send the update to the doc updater", -> + oldFiles = [ file: @entity, path: @path ] + @documentUpdaterHandler.updateProjectStructure + .calledWith(project_id, userId, {oldFiles}) + .should.equal true + describe "a doc", -> beforeEach (done) -> - @ProjectEntityHandler._cleanUpDoc = sinon.stub().callsArg(2) - @ProjectEntityHandler._cleanUpEntity @project, @entity = {_id: @entity_id}, 'doc', done + @path = "/file/system/path.tex" + @ProjectEntityHandler._cleanUpDoc = sinon.stub().callsArg(4) + @entity = {_id: @entity_id} + @ProjectEntityHandler._cleanUpEntity @project, @entity, 'doc', @path, userId, done it "should clean up the doc", -> @ProjectEntityHandler._cleanUpDoc - .calledWith(@project, @entity) + .calledWith(@project, @entity, @path, userId) .should.equal true describe "a folder", -> beforeEach (done) -> @folder = folders: [ - fileRefs: [ @file1 = {_id: "file-id-1" } ] - docs: [ @doc1 = { _id: "doc-id-1" } ] + name: "subfolder" + fileRefs: [ @file1 = { _id: "file-id-1", name: "file-name-1"} ] + docs: [ @doc1 = { _id: "doc-id-1", name: "doc-name-1" } ] folders: [] ] - fileRefs: [ @file2 = { _id: "file-id-2" } ] - docs: [ @doc2 = { _id: "doc-id-2" } ] + fileRefs: [ @file2 = { _id: "file-id-2", name: "file-name-2" } ] + docs: [ @doc2 = { _id: "doc-id-2", name: "doc-name-2" } ] - @ProjectEntityHandler._cleanUpDoc = sinon.stub().callsArg(2) - @ProjectEntityHandler._cleanUpFile = sinon.stub().callsArg(2) - @ProjectEntityHandler._cleanUpEntity @project, @folder, "folder", done + @ProjectEntityHandler._cleanUpDoc = sinon.stub().callsArg(4) + @ProjectEntityHandler._cleanUpFile = sinon.stub().callsArg(4) + path = "/folder" + @ProjectEntityHandler._cleanUpEntity @project, @folder, "folder", path, userId, done it "should clean up all sub files", -> - @ProjectEntityHandler._cleanUpFile.calledWith(@project, @file1).should.equal true - @ProjectEntityHandler._cleanUpFile.calledWith(@project, @file2).should.equal true + @ProjectEntityHandler._cleanUpFile + .calledWith(@project, @file1, "/folder/subfolder/file-name-1", userId) + .should.equal true + @ProjectEntityHandler._cleanUpFile + .calledWith(@project, @file2, "/folder/file-name-2", userId) + .should.equal true it "should clean up all sub docs", -> - @ProjectEntityHandler._cleanUpDoc.calledWith(@project, @doc1).should.equal true - @ProjectEntityHandler._cleanUpDoc.calledWith(@project, @doc2).should.equal true + @ProjectEntityHandler._cleanUpDoc + .calledWith(@project, @doc1, "/folder/subfolder/doc-name-1", userId) + .should.equal true + @ProjectEntityHandler._cleanUpDoc + .calledWith(@project, @doc2, "/folder/doc-name-2", userId) + .should.equal true describe 'moveEntity', -> beforeEach -> @@ -1116,6 +1136,7 @@ describe 'ProjectEntityHandler', -> @doc = _id: ObjectId() name: "test.tex" + @path = "/path/to/doc" @ProjectEntityHandler.unsetRootDoc = sinon.stub().callsArg(1) @ProjectEntityHandler._insertDeletedDocReference = sinon.stub().callsArg(2) @documentUpdaterHandler.deleteDoc = sinon.stub().callsArg(2) @@ -1125,7 +1146,7 @@ describe 'ProjectEntityHandler', -> describe "when the doc is the root doc", -> beforeEach -> @project.rootDoc_id = @doc._id - @ProjectEntityHandler._cleanUpDoc @project, @doc, @callback + @ProjectEntityHandler._cleanUpDoc @project, @doc, @path, userId, @callback it "should unset the root doc", -> @ProjectEntityHandler.unsetRootDoc @@ -1146,13 +1167,19 @@ describe 'ProjectEntityHandler', -> .calledWith(project_id, @doc._id.toString()) .should.equal true + it "should should send the update to the doc updater", -> + oldDocs = [ doc: @doc, path: @path ] + @documentUpdaterHandler.updateProjectStructure + .calledWith(project_id, userId, {oldDocs}) + .should.equal true + it "should call the callback", -> @callback.called.should.equal true describe "when the doc is not the root doc", -> beforeEach -> @project.rootDoc_id = ObjectId() - @ProjectEntityHandler._cleanUpDoc @project, @doc, @callback + @ProjectEntityHandler._cleanUpDoc @project, @doc, @path, userId, @callback it "should not unset the root doc", -> @ProjectEntityHandler.unsetRootDoc.called.should.equal false diff --git a/services/web/test/unit/coffee/ThirdPartyDataStore/TpdsUpdateHandlerTests.coffee b/services/web/test/unit/coffee/ThirdPartyDataStore/TpdsUpdateHandlerTests.coffee index dedd3ea7c8..3984d6341f 100644 --- a/services/web/test/unit/coffee/ThirdPartyDataStore/TpdsUpdateHandlerTests.coffee +++ b/services/web/test/unit/coffee/ThirdPartyDataStore/TpdsUpdateHandlerTests.coffee @@ -8,7 +8,7 @@ describe 'TpdsUpdateHandler', -> beforeEach -> @requestQueuer = {} @updateMerger = - deleteUpdate: (user_id, path, source, cb)->cb() + deleteUpdate: (user_id, project_id, path, source, cb)->cb() mergeUpdate:(user_id, project_id, path, update, source, cb)->cb() @editorController = {} @project_id = "dsjajilknaksdn" @@ -107,11 +107,13 @@ describe 'TpdsUpdateHandler', -> it 'should call deleteEntity in the collaberation manager', (done)-> path = "/delete/this" update = {} - @updateMerger.deleteUpdate = sinon.stub().callsArg(3) + @updateMerger.deleteUpdate = sinon.stub().callsArg(4) @handler.deleteUpdate @user_id, @project.name, path, @source, => @projectDeleter.markAsDeletedByExternalSource.calledWith(@project._id).should.equal false - @updateMerger.deleteUpdate.calledWith(@project_id, path, @source).should.equal true + @updateMerger.deleteUpdate + .calledWith(@user_id, @project_id, path, @source) + .should.equal true done() it 'should mark the project as deleted by external source if path is a single slash', (done)-> diff --git a/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee b/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee index e20419765f..cb2aa059ea 100644 --- a/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee +++ b/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee @@ -145,13 +145,13 @@ describe 'UpdateMerger :', -> it 'should get the element id', -> @projectLocator.findElementByPath = sinon.spy() - @updateMerger.deleteUpdate @project_id, @path, @source, -> + @updateMerger.deleteUpdate @user_id, @project_id, @path, @source, -> @projectLocator.findElementByPath.calledWith(@project_id, @path).should.equal true it 'should delete the entity in the editor controller with the correct type', (done)-> @entity.lines = [] - mock = sinon.mock(@editorController).expects("deleteEntity").withArgs(@project_id, @entity_id, @type, @source).callsArg(4) - @updateMerger.deleteUpdate @project_id, @path, @source, -> + mock = sinon.mock(@editorController).expects("deleteEntity").withArgs(@project_id, @entity_id, @type, @source, @user_id).callsArg(5) + @updateMerger.deleteUpdate @user_id, @project_id, @path, @source, -> mock.verify() done()