From 2b36a443c95cbcecb578ed6b8265d82ff98a5b31 Mon Sep 17 00:00:00 2001 From: James Allen Date: Thu, 2 Mar 2017 16:45:24 +0000 Subject: [PATCH] Pull track changes backend into a module --- .../Features/Chat/ChatController.coffee | 37 ++- .../Comments/CommentsController.coffee | 111 ------- .../Project/ProjectEditorHandler.coffee | 4 +- .../TrackChanges/RangesManager.coffee | 23 -- .../TrackChangesController.coffee | 42 --- .../TrackChanges/TrackChangesManager.coffee | 5 - services/web/app/coffee/router.coffee | 16 - .../coffee/Chat/ChatControllerTests.coffee | 78 ++++- .../Comments/CommentsControllerTests.coffee | 284 ------------------ .../TrackChanges/RangesManagerTests.coffee | 55 ---- 10 files changed, 113 insertions(+), 542 deletions(-) delete mode 100644 services/web/app/coffee/Features/Comments/CommentsController.coffee delete mode 100644 services/web/app/coffee/Features/TrackChanges/RangesManager.coffee delete mode 100644 services/web/app/coffee/Features/TrackChanges/TrackChangesController.coffee delete mode 100644 services/web/app/coffee/Features/TrackChanges/TrackChangesManager.coffee delete mode 100644 services/web/test/UnitTests/coffee/Comments/CommentsControllerTests.coffee delete mode 100644 services/web/test/UnitTests/coffee/TrackChanges/RangesManagerTests.coffee diff --git a/services/web/app/coffee/Features/Chat/ChatController.coffee b/services/web/app/coffee/Features/Chat/ChatController.coffee index 3090f4f108..b163df8158 100644 --- a/services/web/app/coffee/Features/Chat/ChatController.coffee +++ b/services/web/app/coffee/Features/Chat/ChatController.coffee @@ -4,9 +4,9 @@ logger = require("logger-sharelatex") AuthenticationController = require('../Authentication/AuthenticationController') UserInfoManager = require('../User/UserInfoManager') UserInfoController = require('../User/UserInfoController') -CommentsController = require('../Comments/CommentsController') +async = require "async" -module.exports = +module.exports = ChatController = sendMessage: (req, res, next)-> project_id = req.params.project_id content = req.body.content @@ -28,7 +28,38 @@ module.exports = logger.log project_id:project_id, query:query, "getting messages" ChatApiHandler.getGlobalMessages project_id, query.limit, query.before, (err, messages) -> return next(err) if err? - CommentsController._injectUserInfoIntoThreads {global: { messages: messages }}, (err) -> + ChatController._injectUserInfoIntoThreads {global: { messages: messages }}, (err) -> return next(err) if err? logger.log length: messages?.length, "sending messages to client" res.json messages + + _injectUserInfoIntoThreads: (threads, callback = (error, threads) ->) -> + userCache = {} + getUserDetails = (user_id, callback = (error, user) ->) -> + return callback(null, userCache[user_id]) if userCache[user_id]? + UserInfoManager.getPersonalInfo user_id, (err, user) -> + return callback(error) if error? + user = UserInfoController.formatPersonalInfo user + userCache[user_id] = user + callback null, user + + jobs = [] + for thread_id, thread of threads + do (thread) -> + if thread.resolved + jobs.push (cb) -> + getUserDetails thread.resolved_by_user_id, (error, user) -> + cb(error) if error? + thread.resolved_by_user = user + cb() + for message in thread.messages + do (message) -> + jobs.push (cb) -> + getUserDetails message.user_id, (error, user) -> + cb(error) if error? + message.user = user + cb() + + async.series jobs, (error) -> + return callback(error) if error? + return callback null, threads \ No newline at end of file diff --git a/services/web/app/coffee/Features/Comments/CommentsController.coffee b/services/web/app/coffee/Features/Comments/CommentsController.coffee deleted file mode 100644 index bda006eb8f..0000000000 --- a/services/web/app/coffee/Features/Comments/CommentsController.coffee +++ /dev/null @@ -1,111 +0,0 @@ -ChatApiHandler = require("../Chat/ChatApiHandler") -EditorRealTimeController = require("../Editor/EditorRealTimeController") -logger = require("logger-sharelatex") -AuthenticationController = require('../Authentication/AuthenticationController') -UserInfoManager = require('../User/UserInfoManager') -UserInfoController = require('../User/UserInfoController') -DocumentUpdaterHandler = require "../DocumentUpdater/DocumentUpdaterHandler" -async = require "async" - -module.exports = CommentsController = - sendComment: (req, res, next) -> - {project_id, thread_id} = req.params - content = req.body.content - user_id = AuthenticationController.getLoggedInUserId(req) - if !user_id? - err = new Error('no logged-in user') - return next(err) - logger.log {project_id, thread_id, user_id, content}, "sending comment" - ChatApiHandler.sendComment project_id, thread_id, user_id, content, (err, comment) -> - return next(err) if err? - UserInfoManager.getPersonalInfo comment.user_id, (err, user) -> - return next(err) if err? - comment.user = UserInfoController.formatPersonalInfo(user) - EditorRealTimeController.emitToRoom project_id, "new-comment", thread_id, comment, (err) -> - res.send 204 - - getThreads: (req, res, next) -> - {project_id} = req.params - logger.log {project_id}, "getting comment threads for project" - ChatApiHandler.getThreads project_id, (err, threads) -> - return next(err) if err? - CommentsController._injectUserInfoIntoThreads threads, (error, threads) -> - return next(err) if err? - res.json threads - - resolveThread: (req, res, next) -> - {project_id, thread_id} = req.params - user_id = AuthenticationController.getLoggedInUserId(req) - logger.log {project_id, thread_id, user_id}, "resolving comment thread" - ChatApiHandler.resolveThread project_id, thread_id, user_id, (err) -> - return next(err) if err? - UserInfoManager.getPersonalInfo user_id, (err, user) -> - return next(err) if err? - EditorRealTimeController.emitToRoom project_id, "resolve-thread", thread_id, UserInfoController.formatPersonalInfo(user), (err)-> - res.send 204 - - reopenThread: (req, res, next) -> - {project_id, thread_id} = req.params - logger.log {project_id, thread_id}, "reopening comment thread" - ChatApiHandler.reopenThread project_id, thread_id, (err, threads) -> - return next(err) if err? - EditorRealTimeController.emitToRoom project_id, "reopen-thread", thread_id, (err)-> - res.send 204 - - deleteThread: (req, res, next) -> - {project_id, doc_id, thread_id} = req.params - logger.log {project_id, doc_id, thread_id}, "deleting comment thread" - DocumentUpdaterHandler.deleteThread project_id, doc_id, thread_id, (err) -> - return next(err) if err? - ChatApiHandler.deleteThread project_id, thread_id, (err, threads) -> - return next(err) if err? - EditorRealTimeController.emitToRoom project_id, "delete-thread", thread_id, (err)-> - res.send 204 - - editMessage: (req, res, next) -> - {project_id, thread_id, message_id} = req.params - {content} = req.body - logger.log {project_id, thread_id, message_id}, "editing message thread" - ChatApiHandler.editMessage project_id, thread_id, message_id, content, (err) -> - return next(err) if err? - EditorRealTimeController.emitToRoom project_id, "edit-message", thread_id, message_id, content, (err)-> - res.send 204 - - deleteMessage: (req, res, next) -> - {project_id, thread_id, message_id} = req.params - logger.log {project_id, thread_id, message_id}, "deleting message" - ChatApiHandler.deleteMessage project_id, thread_id, message_id, (err, threads) -> - return next(err) if err? - EditorRealTimeController.emitToRoom project_id, "delete-message", thread_id, message_id, (err)-> - res.send 204 - - _injectUserInfoIntoThreads: (threads, callback = (error, threads) ->) -> - userCache = {} - getUserDetails = (user_id, callback = (error, user) ->) -> - return callback(null, userCache[user_id]) if userCache[user_id]? - UserInfoManager.getPersonalInfo user_id, (err, user) -> - return callback(error) if error? - user = UserInfoController.formatPersonalInfo user - userCache[user_id] = user - callback null, user - - jobs = [] - for thread_id, thread of threads - do (thread) -> - if thread.resolved - jobs.push (cb) -> - getUserDetails thread.resolved_by_user_id, (error, user) -> - cb(error) if error? - thread.resolved_by_user = user - cb() - for message in thread.messages - do (message) -> - jobs.push (cb) -> - getUserDetails message.user_id, (error, user) -> - cb(error) if error? - message.user = user - cb() - - async.series jobs, (error) -> - return callback(error) if error? - return callback null, threads \ No newline at end of file diff --git a/services/web/app/coffee/Features/Project/ProjectEditorHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEditorHandler.coffee index 3af40bf162..8ec25ace10 100644 --- a/services/web/app/coffee/Features/Project/ProjectEditorHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEditorHandler.coffee @@ -1,6 +1,8 @@ _ = require("underscore") module.exports = ProjectEditorHandler = + trackChangesAvailable: false + buildProjectModelView: (project, members, invites) -> result = _id : project._id @@ -38,7 +40,7 @@ module.exports = ProjectEditorHandler = templates: false references: false trackChanges: false - trackChangesVisible: trackChangesVisible + trackChangesVisible: ProjectEditorHandler.trackChangesAvailable and trackChangesVisible }) return result diff --git a/services/web/app/coffee/Features/TrackChanges/RangesManager.coffee b/services/web/app/coffee/Features/TrackChanges/RangesManager.coffee deleted file mode 100644 index 09e6b52ed1..0000000000 --- a/services/web/app/coffee/Features/TrackChanges/RangesManager.coffee +++ /dev/null @@ -1,23 +0,0 @@ -DocumentUpdaterHandler = require "../DocumentUpdater/DocumentUpdaterHandler" -DocstoreManager = require "../Docstore/DocstoreManager" -UserInfoManager = require "../User/UserInfoManager" -async = require "async" - -module.exports = RangesManager = - getAllRanges: (project_id, callback = (error, docs) ->) -> - DocumentUpdaterHandler.flushProjectToMongo project_id, (error) -> - return callback(error) if error? - DocstoreManager.getAllRanges project_id, callback - - getAllChangesUsers: (project_id, callback = (error, users) ->) -> - user_ids = {} - RangesManager.getAllRanges project_id, (error, docs) -> - return callback(error) if error? - jobs = [] - for doc in docs - for change in doc.ranges?.changes or [] - user_ids[change.metadata.user_id] = true - - async.mapSeries Object.keys(user_ids), (user_id, cb) -> - UserInfoManager.getPersonalInfo user_id, cb - , callback \ No newline at end of file diff --git a/services/web/app/coffee/Features/TrackChanges/TrackChangesController.coffee b/services/web/app/coffee/Features/TrackChanges/TrackChangesController.coffee deleted file mode 100644 index d71481a7fd..0000000000 --- a/services/web/app/coffee/Features/TrackChanges/TrackChangesController.coffee +++ /dev/null @@ -1,42 +0,0 @@ -RangesManager = require "./RangesManager" -logger = require "logger-sharelatex" -UserInfoController = require "../User/UserInfoController" -DocumentUpdaterHandler = require "../DocumentUpdater/DocumentUpdaterHandler" -EditorRealTimeController = require("../Editor/EditorRealTimeController") -TrackChangesManager = require "./TrackChangesManager" - -module.exports = TrackChangesController = - getAllRanges: (req, res, next) -> - project_id = req.params.project_id - logger.log {project_id}, "request for project ranges" - RangesManager.getAllRanges project_id, (error, docs = []) -> - return next(error) if error? - docs = ({id: d._id, ranges: d.ranges} for d in docs) - res.json docs - - getAllChangesUsers: (req, res, next) -> - project_id = req.params.project_id - logger.log {project_id}, "request for project range users" - RangesManager.getAllChangesUsers project_id, (error, users) -> - return next(error) if error? - users = (UserInfoController.formatPersonalInfo(user) for user in users) - # Get rid of any anonymous/deleted user objects - users = users.filter (u) -> u?.id? - res.json users - - acceptChange: (req, res, next) -> - {project_id, doc_id, change_id} = req.params - logger.log {project_id, doc_id, change_id}, "request to accept change" - DocumentUpdaterHandler.acceptChange project_id, doc_id, change_id, (error) -> - return next(error) if error? - EditorRealTimeController.emitToRoom project_id, "accept-change", doc_id, change_id, (err)-> - res.send 204 - - toggleTrackChanges: (req, res, next) -> - {project_id} = req.params - track_changes_on = !!req.body.on - logger.log {project_id, track_changes_on}, "request to toggle track changes" - TrackChangesManager.toggleTrackChanges project_id, track_changes_on, (error) -> - return next(error) if error? - EditorRealTimeController.emitToRoom project_id, "toggle-track-changes", track_changes_on, (err)-> - res.send 204 diff --git a/services/web/app/coffee/Features/TrackChanges/TrackChangesManager.coffee b/services/web/app/coffee/Features/TrackChanges/TrackChangesManager.coffee deleted file mode 100644 index 8eb7c10c29..0000000000 --- a/services/web/app/coffee/Features/TrackChanges/TrackChangesManager.coffee +++ /dev/null @@ -1,5 +0,0 @@ -Project = require("../../models/Project").Project - -module.exports = TrackChangesManager = - toggleTrackChanges: (project_id, track_changes_on, callback = (error) ->) -> - Project.update {_id: project_id}, {track_changes: track_changes_on}, callback diff --git a/services/web/app/coffee/router.coffee b/services/web/app/coffee/router.coffee index 62d5ec0865..53e92eb7a6 100644 --- a/services/web/app/coffee/router.coffee +++ b/services/web/app/coffee/router.coffee @@ -40,8 +40,6 @@ AuthorizationMiddlewear = require('./Features/Authorization/AuthorizationMiddlew BetaProgramController = require('./Features/BetaProgram/BetaProgramController') AnalyticsRouter = require('./Features/Analytics/AnalyticsRouter') AnnouncementsController = require("./Features/Announcements/AnnouncementsController") -TrackChangesController = require("./Features/TrackChanges/TrackChangesController") -CommentsController = require "./Features/Comments/CommentsController" logger = require("logger-sharelatex") _ = require("underscore") @@ -177,11 +175,6 @@ module.exports = class Router webRouter.get "/project/:Project_id/doc/:doc_id/diff", AuthorizationMiddlewear.ensureUserCanReadProject, HistoryController.proxyToHistoryApi webRouter.post "/project/:Project_id/doc/:doc_id/version/:version_id/restore", AuthorizationMiddlewear.ensureUserCanReadProject, HistoryController.proxyToHistoryApi - webRouter.get "/project/:project_id/ranges", AuthorizationMiddlewear.ensureUserCanReadProject, TrackChangesController.getAllRanges - webRouter.get "/project/:project_id/changes/users", AuthorizationMiddlewear.ensureUserCanReadProject, TrackChangesController.getAllChangesUsers - webRouter.post "/project/:project_id/doc/:doc_id/changes/:change_id/accept", AuthorizationMiddlewear.ensureUserCanWriteProjectContent, TrackChangesController.acceptChange - webRouter.post "/project/:project_id/track_changes", AuthorizationMiddlewear.ensureUserCanWriteProjectContent, TrackChangesController.toggleTrackChanges - webRouter.get '/Project/:Project_id/download/zip', AuthorizationMiddlewear.ensureUserCanReadProject, ProjectDownloadsController.downloadProject webRouter.get '/project/download/zip', AuthorizationMiddlewear.ensureUserCanReadMultipleProjects, ProjectDownloadsController.downloadMultipleProjects @@ -232,15 +225,6 @@ module.exports = class Router webRouter.get "/project/:project_id/messages", AuthorizationMiddlewear.ensureUserCanReadProject, ChatController.getMessages webRouter.post "/project/:project_id/messages", AuthorizationMiddlewear.ensureUserCanReadProject, ChatController.sendMessage - - # Note: Read only users can still comment - webRouter.post "/project/:project_id/thread/:thread_id/messages", AuthorizationMiddlewear.ensureUserCanReadProject, CommentsController.sendComment - webRouter.get "/project/:project_id/threads", AuthorizationMiddlewear.ensureUserCanReadProject, CommentsController.getThreads - webRouter.post "/project/:project_id/thread/:thread_id/resolve", AuthorizationMiddlewear.ensureUserCanWriteProjectContent, CommentsController.resolveThread - webRouter.post "/project/:project_id/thread/:thread_id/reopen", AuthorizationMiddlewear.ensureUserCanWriteProjectContent, CommentsController.reopenThread - webRouter.delete "/project/:project_id/doc/:doc_id/thread/:thread_id", AuthorizationMiddlewear.ensureUserCanWriteProjectContent, CommentsController.deleteThread - webRouter.post "/project/:project_id/thread/:thread_id/messages/:message_id/edit", AuthorizationMiddlewear.ensureUserCanWriteProjectContent, CommentsController.editMessage - webRouter.delete "/project/:project_id/thread/:thread_id/messages/:message_id", AuthorizationMiddlewear.ensureUserCanWriteProjectContent, CommentsController.deleteMessage webRouter.post "/project/:Project_id/references/index", AuthorizationMiddlewear.ensureUserCanReadProject, ReferencesController.index webRouter.post "/project/:Project_id/references/indexAll", AuthorizationMiddlewear.ensureUserCanReadProject, ReferencesController.indexAll diff --git a/services/web/test/UnitTests/coffee/Chat/ChatControllerTests.coffee b/services/web/test/UnitTests/coffee/Chat/ChatControllerTests.coffee index 851eb47f09..8a7fd757ea 100644 --- a/services/web/test/UnitTests/coffee/Chat/ChatControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/Chat/ChatControllerTests.coffee @@ -69,7 +69,7 @@ describe "ChatController", -> @req.query = limit: @limit = "30" before: @before = "12345" - @CommentsController._injectUserInfoIntoThreads = sinon.stub().yields() + @ChatController._injectUserInfoIntoThreads = sinon.stub().yields() @ChatApiHandler.getGlobalMessages = sinon.stub().yields(null, @messages = ["mock", "messages"]) @ChatController.getMessages @req, @res @@ -79,4 +79,78 @@ describe "ChatController", -> .should.equal true it "should return the messages", -> - @res.json.calledWith(@messages).should.equal true \ No newline at end of file + @res.json.calledWith(@messages).should.equal true + + describe "_injectUserInfoIntoThreads", -> + beforeEach -> + @users = { + "user_id_1": { + "mock": "user_1" + } + "user_id_2": { + "mock": "user_2" + } + } + @UserInfoManager.getPersonalInfo = (user_id, callback) => + return callback(null, @users[user_id]) + sinon.spy @UserInfoManager, "getPersonalInfo" + @UserInfoController.formatPersonalInfo = (user) -> + return { "formatted": user["mock"] } + + it "should inject a user object into messaged and resolved data", (done) -> + @ChatController._injectUserInfoIntoThreads { + thread1: { + resolved: true + resolved_by_user_id: "user_id_1" + messages: [{ + user_id: "user_id_1" + content: "foo" + }, { + user_id: "user_id_2" + content: "bar" + }] + }, + thread2: { + messages: [{ + user_id: "user_id_1" + content: "baz" + }] + } + }, (error, threads) -> + expect(threads).to.deep.equal { + thread1: { + resolved: true + resolved_by_user_id: "user_id_1" + resolved_by_user: { "formatted": "user_1" } + messages: [{ + user_id: "user_id_1" + user: { "formatted": "user_1" } + content: "foo" + }, { + user_id: "user_id_2" + user: { "formatted": "user_2" } + content: "bar" + }] + }, + thread2: { + messages: [{ + user_id: "user_id_1" + user: { "formatted": "user_1" } + content: "baz" + }] + } + } + done() + + it "should only need to look up each user once", (done) -> + @ChatController._injectUserInfoIntoThreads [{ + messages: [{ + user_id: "user_id_1" + content: "foo" + }, { + user_id: "user_id_1" + content: "bar" + }] + }], (error, threads) => + @UserInfoManager.getPersonalInfo.calledOnce.should.equal true + done() \ No newline at end of file diff --git a/services/web/test/UnitTests/coffee/Comments/CommentsControllerTests.coffee b/services/web/test/UnitTests/coffee/Comments/CommentsControllerTests.coffee deleted file mode 100644 index e55f0d04da..0000000000 --- a/services/web/test/UnitTests/coffee/Comments/CommentsControllerTests.coffee +++ /dev/null @@ -1,284 +0,0 @@ -should = require('chai').should() -SandboxedModule = require('sandboxed-module') -assert = require('assert') -path = require('path') -sinon = require('sinon') -modulePath = path.join __dirname, "../../../../app/js/Features/Comments/CommentsController" -expect = require("chai").expect - -describe "CommentsController", -> - beforeEach -> - @user_id = 'mock-user-id' - @settings = {} - @ChatApiHandler = {} - @EditorRealTimeController = - emitToRoom:sinon.stub() - @AuthenticationController = - getLoggedInUserId: sinon.stub().returns(@user_id) - @CommentsController = SandboxedModule.require modulePath, requires: - "settings-sharelatex": @settings - "logger-sharelatex": log: -> - "../Chat/ChatApiHandler": @ChatApiHandler - "../Editor/EditorRealTimeController": @EditorRealTimeController - '../Authentication/AuthenticationController': @AuthenticationController - '../User/UserInfoManager': @UserInfoManager = {} - '../User/UserInfoController': @UserInfoController = {} - "../DocumentUpdater/DocumentUpdaterHandler": @DocumentUpdaterHandler = {} - @req = {} - @res = - json: sinon.stub() - send: sinon.stub() - - describe "sendComment", -> - beforeEach -> - @req.params = - project_id: @project_id = "mock-project-id" - thread_id: @thread_id = "mock-thread-id" - @req.body = - content: @content = "message-content" - @UserInfoManager.getPersonalInfo = sinon.stub().yields(null, @user = {"unformatted": "user"}) - @UserInfoController.formatPersonalInfo = sinon.stub().returns(@formatted_user = {"formatted": "user"}) - @ChatApiHandler.sendComment = sinon.stub().yields(null, @message = {"mock": "message", user_id: @user_id}) - @CommentsController.sendComment @req, @res - - it "should look up the user", -> - @UserInfoManager.getPersonalInfo - .calledWith(@user_id) - .should.equal true - - it "should format and inject the user into the comment", -> - @UserInfoController.formatPersonalInfo - .calledWith(@user) - .should.equal true - @message.user.should.deep.equal @formatted_user - - it "should tell the chat handler about the message", -> - @ChatApiHandler.sendComment - .calledWith(@project_id, @thread_id, @user_id, @content) - .should.equal true - - it "should tell the editor real time controller about the update with the data from the chat handler", -> - @EditorRealTimeController.emitToRoom - .calledWith(@project_id, "new-comment", @thread_id, @message) - .should.equal true - - it "should return a 204 status code", -> - @res.send.calledWith(204).should.equal true - - describe "getThreads", -> - beforeEach -> - @req.params = - project_id: @project_id = "mock-project-id" - @ChatApiHandler.getThreads = sinon.stub().yields(null, @threads = {"mock", "threads"}) - @CommentsController._injectUserInfoIntoThreads = sinon.stub().yields(null, @threads) - @CommentsController.getThreads @req, @res - - it "should ask the chat handler about the request", -> - @ChatApiHandler.getThreads - .calledWith(@project_id) - .should.equal true - - it "should inject the user details into the threads", -> - @CommentsController._injectUserInfoIntoThreads - .calledWith(@threads) - .should.equal true - - it "should return the messages", -> - @res.json.calledWith(@threads).should.equal true - - describe "resolveThread", -> - beforeEach -> - @req.params = - project_id: @project_id = "mock-project-id" - thread_id: @thread_id = "mock-thread-id" - @ChatApiHandler.resolveThread = sinon.stub().yields() - @UserInfoManager.getPersonalInfo = sinon.stub().yields(null, @user = {"unformatted": "user"}) - @UserInfoController.formatPersonalInfo = sinon.stub().returns(@formatted_user = {"formatted": "user"}) - @CommentsController.resolveThread @req, @res - - it "should ask the chat handler to resolve the thread", -> - @ChatApiHandler.resolveThread - .calledWith(@project_id, @thread_id) - .should.equal true - - it "should look up the user", -> - @UserInfoManager.getPersonalInfo - .calledWith(@user_id) - .should.equal true - - it "should tell the client the comment was resolved", -> - @EditorRealTimeController.emitToRoom - .calledWith(@project_id, "resolve-thread", @thread_id, @formatted_user) - .should.equal true - - it "should return a success code", -> - @res.send.calledWith(204).should.equal - - describe "reopenThread", -> - beforeEach -> - @req.params = - project_id: @project_id = "mock-project-id" - thread_id: @thread_id = "mock-thread-id" - @ChatApiHandler.reopenThread = sinon.stub().yields() - @CommentsController.reopenThread @req, @res - - it "should ask the chat handler to reopen the thread", -> - @ChatApiHandler.reopenThread - .calledWith(@project_id, @thread_id) - .should.equal true - - it "should tell the client the comment was resolved", -> - @EditorRealTimeController.emitToRoom - .calledWith(@project_id, "reopen-thread", @thread_id) - .should.equal true - - it "should return a success code", -> - @res.send.calledWith(204).should.equal - - describe "deleteThread", -> - beforeEach -> - @req.params = - project_id: @project_id = "mock-project-id" - doc_id: @doc_id = "mock-doc-id" - thread_id: @thread_id = "mock-thread-id" - @DocumentUpdaterHandler.deleteThread = sinon.stub().yields() - @ChatApiHandler.deleteThread = sinon.stub().yields() - @CommentsController.deleteThread @req, @res - - it "should ask the doc udpater to delete the thread", -> - @DocumentUpdaterHandler.deleteThread - .calledWith(@project_id, @doc_id, @thread_id) - .should.equal true - - it "should ask the chat handler to delete the thread", -> - @ChatApiHandler.deleteThread - .calledWith(@project_id, @thread_id) - .should.equal true - - it "should tell the client the thread was deleted", -> - @EditorRealTimeController.emitToRoom - .calledWith(@project_id, "delete-thread", @thread_id) - .should.equal true - - it "should return a success code", -> - @res.send.calledWith(204).should.equal - - describe "editMessage", -> - beforeEach -> - @req.params = - project_id: @project_id = "mock-project-id" - thread_id: @thread_id = "mock-thread-id" - message_id: @message_id = "mock-thread-id" - @req.body = - content: @content = "mock-content" - @ChatApiHandler.editMessage = sinon.stub().yields() - @CommentsController.editMessage @req, @res - - it "should ask the chat handler to edit the comment", -> - @ChatApiHandler.editMessage - .calledWith(@project_id, @thread_id, @message_id, @content) - .should.equal true - - it "should tell the client the comment was edited", -> - @EditorRealTimeController.emitToRoom - .calledWith(@project_id, "edit-message", @thread_id, @message_id, @content) - .should.equal true - - it "should return a success code", -> - @res.send.calledWith(204).should.equal - - describe "deleteMessage", -> - beforeEach -> - @req.params = - project_id: @project_id = "mock-project-id" - thread_id: @thread_id = "mock-thread-id" - message_id: @message_id = "mock-thread-id" - @ChatApiHandler.deleteMessage = sinon.stub().yields() - @CommentsController.deleteMessage @req, @res - - it "should ask the chat handler to deleted the message", -> - @ChatApiHandler.deleteMessage - .calledWith(@project_id, @thread_id, @message_id) - .should.equal true - - it "should tell the client the message was deleted", -> - @EditorRealTimeController.emitToRoom - .calledWith(@project_id, "delete-message", @thread_id, @message_id) - .should.equal true - - it "should return a success code", -> - @res.send.calledWith(204).should.equal - - describe "_injectUserInfoIntoThreads", -> - beforeEach -> - @users = { - "user_id_1": { - "mock": "user_1" - } - "user_id_2": { - "mock": "user_2" - } - } - @UserInfoManager.getPersonalInfo = (user_id, callback) => - return callback(null, @users[user_id]) - sinon.spy @UserInfoManager, "getPersonalInfo" - @UserInfoController.formatPersonalInfo = (user) -> - return { "formatted": user["mock"] } - - it "should inject a user object into messaged and resolved data", (done) -> - @CommentsController._injectUserInfoIntoThreads { - thread1: { - resolved: true - resolved_by_user_id: "user_id_1" - messages: [{ - user_id: "user_id_1" - content: "foo" - }, { - user_id: "user_id_2" - content: "bar" - }] - }, - thread2: { - messages: [{ - user_id: "user_id_1" - content: "baz" - }] - } - }, (error, threads) -> - expect(threads).to.deep.equal { - thread1: { - resolved: true - resolved_by_user_id: "user_id_1" - resolved_by_user: { "formatted": "user_1" } - messages: [{ - user_id: "user_id_1" - user: { "formatted": "user_1" } - content: "foo" - }, { - user_id: "user_id_2" - user: { "formatted": "user_2" } - content: "bar" - }] - }, - thread2: { - messages: [{ - user_id: "user_id_1" - user: { "formatted": "user_1" } - content: "baz" - }] - } - } - done() - - it "should only need to look up each user once", (done) -> - @CommentsController._injectUserInfoIntoThreads [{ - messages: [{ - user_id: "user_id_1" - content: "foo" - }, { - user_id: "user_id_1" - content: "bar" - }] - }], (error, threads) => - @UserInfoManager.getPersonalInfo.calledOnce.should.equal true - done() \ No newline at end of file diff --git a/services/web/test/UnitTests/coffee/TrackChanges/RangesManagerTests.coffee b/services/web/test/UnitTests/coffee/TrackChanges/RangesManagerTests.coffee deleted file mode 100644 index b9c95040c1..0000000000 --- a/services/web/test/UnitTests/coffee/TrackChanges/RangesManagerTests.coffee +++ /dev/null @@ -1,55 +0,0 @@ -should = require('chai').should() -SandboxedModule = require('sandboxed-module') -assert = require('assert') -sinon = require('sinon') -path = require "path" -modulePath = path.join __dirname, "../../../../app/js/Features/TrackChanges/RangesManager" -expect = require("chai").expect - -describe "RangesManager", -> - beforeEach -> - @RangesManager = SandboxedModule.require modulePath, requires: - "../DocumentUpdater/DocumentUpdaterHandler": @DocumentUpdaterHandler = {} - "../Docstore/DocstoreManager": @DocstoreManager = {} - "../User/UserInfoManager": @UserInfoManager = {} - - describe "getAllChangesUsers", -> - beforeEach -> - @project_id = "mock-project-id" - @user_id1 = "mock-user-id-1" - @user_id1 = "mock-user-id-2" - @docs = [{ - ranges: - changes: [{ - op: { i: "foo", p: 42 } - metadata: - user_id: @user_id1 - }, { - op: { i: "bar", p: 102 } - metadata: - user_id: @user_id2 - }] - }, { - ranges: - changes: [{ - op: { i: "baz", p: 3 } - metadata: - user_id: @user_id1 - }] - }] - @users = {} - @users[@user_id1] = {"mock": "user-1"} - @users[@user_id2] = {"mock": "user-2"} - @UserInfoManager.getPersonalInfo = (user_id, callback) => callback null, @users[user_id] - sinon.spy @UserInfoManager, "getPersonalInfo" - @RangesManager.getAllRanges = sinon.stub().yields(null, @docs) - - it "should return an array of unique users", (done) -> - @RangesManager.getAllChangesUsers @project_id, (error, users) => - users.should.deep.equal [{"mock": "user-1"}, {"mock": "user-2"}] - done() - - it "should only call getPersonalInfo once for each user", (done) -> - @RangesManager.getAllChangesUsers @project_id, (error, users) => - @UserInfoManager.getPersonalInfo.calledTwice.should.equal true - done() \ No newline at end of file