From 6ac2aa77a8273a04fedd9fb6b73fbdeadf6fc077 Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 14 Dec 2016 17:38:14 +0000 Subject: [PATCH 1/2] Clean up dead code and add acceptance tests --- services/chat/.gitignore | 1 + services/chat/Gruntfile.coffee | 20 +- .../AuthenticationController.coffee | 23 -- .../Authorization/AuthorizationManager.coffee | 24 -- .../Messages/MessageController.coffee | 84 ------ .../Features/Rooms/RoomController.coffee | 101 -------- .../Sockets/RealTimeEventManager.coffee | 25 -- .../Features/Sockets/SocketManager.coffee | 40 --- .../Features/Users/UserFormatter.coffee | 1 + .../Features/WebApi/WebApiManager.coffee | 30 ++- services/chat/app/coffee/router.coffee | 21 +- services/chat/app/coffee/server.coffee | 9 +- services/chat/package.json | 7 +- .../coffee/GettingMessagesTests.coffee | 73 ++++++ .../coffee/SendingAMessageTests.coffee | 23 ++ .../coffee/helpers/ChatClient.coffee | 16 ++ .../coffee/helpers/MockWebApi.coffee | 27 ++ .../AuthenticationControllerTests.coffee | 71 ------ .../AuthorizationManagerTests.coffee | 55 ---- .../Messages/MessageControllerTests.coffee | 187 -------------- .../coffee/Rooms/RoomControllerTests.coffee | 240 ------------------ .../Sockets/RealTimeEventManagerTests.coffee | 75 ------ 22 files changed, 181 insertions(+), 972 deletions(-) delete mode 100644 services/chat/app/coffee/Features/Authentication/AuthenticationController.coffee delete mode 100644 services/chat/app/coffee/Features/Authorization/AuthorizationManager.coffee delete mode 100644 services/chat/app/coffee/Features/Messages/MessageController.coffee delete mode 100644 services/chat/app/coffee/Features/Rooms/RoomController.coffee delete mode 100644 services/chat/app/coffee/Features/Sockets/RealTimeEventManager.coffee delete mode 100644 services/chat/app/coffee/Features/Sockets/SocketManager.coffee create mode 100644 services/chat/test/acceptance/coffee/GettingMessagesTests.coffee create mode 100644 services/chat/test/acceptance/coffee/SendingAMessageTests.coffee create mode 100644 services/chat/test/acceptance/coffee/helpers/ChatClient.coffee create mode 100644 services/chat/test/acceptance/coffee/helpers/MockWebApi.coffee delete mode 100644 services/chat/test/unit/coffee/Authentication/AuthenticationControllerTests.coffee delete mode 100644 services/chat/test/unit/coffee/Authorization/AuthorizationManagerTests.coffee delete mode 100644 services/chat/test/unit/coffee/Messages/MessageControllerTests.coffee delete mode 100644 services/chat/test/unit/coffee/Rooms/RoomControllerTests.coffee delete mode 100644 services/chat/test/unit/coffee/Sockets/RealTimeEventManagerTests.coffee diff --git a/services/chat/.gitignore b/services/chat/.gitignore index cb03337081..ba6632606f 100644 --- a/services/chat/.gitignore +++ b/services/chat/.gitignore @@ -3,6 +3,7 @@ app.js app/js/ test/unit/js/ +test/acceptance/js/ public/build/ node_modules/ diff --git a/services/chat/Gruntfile.coffee b/services/chat/Gruntfile.coffee index 67a884e377..304d564a74 100644 --- a/services/chat/Gruntfile.coffee +++ b/services/chat/Gruntfile.coffee @@ -30,7 +30,7 @@ module.exports = (grunt) -> dest: './', ext: '.js' - server_tests: + unit_tests: expand: true, flatten: false, cwd: 'test/unit/coffee', @@ -38,10 +38,18 @@ module.exports = (grunt) -> dest: 'test/unit/js/', ext: '.js' + acceptance_tests: + expand: true, + flatten: false, + cwd: 'test/acceptance/coffee', + src: ['**/*.coffee'], + dest: 'test/acceptance/js/', + ext: '.js' + watch: server_coffee: files: ['app/**/*.coffee', 'test/unit/**/*.coffee'] - tasks: ['compile:server', 'compile:server_tests', 'mochaTest'] + tasks: ['compile:server', 'compile:unit_tests', 'mochaTest'] client_coffee: files: ['public/**/*.coffee'] @@ -101,7 +109,12 @@ module.exports = (grunt) -> options: reporter: process.env.MOCHA_RUNNER || "spec" grep: grunt.option("grep") - src: ['test/**/*.js'] + src: ['test/unit/**/*.js'] + acceptance: + options: + reporter: process.env.MOCHA_RUNNER || "spec" + grep: grunt.option("grep") + src: ['test/acceptance/**/*.js'] plato: your_task: @@ -128,4 +141,5 @@ module.exports = (grunt) -> grunt.registerTask 'default', ['compile', 'bunyan', 'execute'] grunt.registerTask 'compileAndCompress', ['compile', 'uglify'] grunt.registerTask 'test:unit', ['compile', 'mochaTest:unit'] + grunt.registerTask 'test:acceptance', ['compile:acceptance_tests', 'mochaTest:acceptance'] diff --git a/services/chat/app/coffee/Features/Authentication/AuthenticationController.coffee b/services/chat/app/coffee/Features/Authentication/AuthenticationController.coffee deleted file mode 100644 index 2b49cdd8c0..0000000000 --- a/services/chat/app/coffee/Features/Authentication/AuthenticationController.coffee +++ /dev/null @@ -1,23 +0,0 @@ -async = require "async" -logger = require "logger-sharelatex" -WebApiManager = require("../WebApi/WebApiManager") -UserFormatter = require("../Users/UserFormatter") - -module.exports = AuthenticationController = - authClient: (client, data, callback = (error) ->) -> - logger.log auth_token: data.auth_token, "authenticating user" - WebApiManager.getUserDetailsFromAuthToken data.auth_token, (error, user) => - if error? - logger.error data: data, client_id: client.id, err: error, "error authenticating user" - return callback("something went wrong") - logger.log user: user, auth_token: data.auth_token, "authenticated user" - user = UserFormatter.formatUserForClientSide user - jobs = [] - for key, value of user - do (key, value) -> - jobs.push (callback) -> client.set key, value, callback - jobs.push (callback) -> client.set "auth_token", data.auth_token, callback - async.series jobs, (error, results) => - callback(error, user) - - diff --git a/services/chat/app/coffee/Features/Authorization/AuthorizationManager.coffee b/services/chat/app/coffee/Features/Authorization/AuthorizationManager.coffee deleted file mode 100644 index 0104f43f64..0000000000 --- a/services/chat/app/coffee/Features/Authorization/AuthorizationManager.coffee +++ /dev/null @@ -1,24 +0,0 @@ -WebApiManager = require "../WebApi/WebApiManager" -SocketManager = require "../Sockets/SocketManager" - -module.exports = AuthorizationManager = - canClientJoinProjectRoom: (client, project_id, callback = (error, authorized) ->) -> - client.get "auth_token", (error, auth_token) -> - return callback(error) if error? - WebApiManager.getProjectCollaborators project_id, auth_token, (error, collaborators) -> - return callback(error) if error? - client.get "id", (error, user_id) -> - return callback(error) if error? - authorized = false - for collaborator in collaborators - if collaborator.id == user_id - authorized = true - break - callback null, authorized - - canClientSendMessageToRoom: (client, room_id, callback = (error, authorized) ->) -> - SocketManager.isClientInRoom(client, room_id, callback) - - canClientReadMessagesInRoom: (client, room_id, callback = (error, authorized) ->) -> - SocketManager.isClientInRoom(client, room_id, callback) - diff --git a/services/chat/app/coffee/Features/Messages/MessageController.coffee b/services/chat/app/coffee/Features/Messages/MessageController.coffee deleted file mode 100644 index e4caa9dc04..0000000000 --- a/services/chat/app/coffee/Features/Messages/MessageController.coffee +++ /dev/null @@ -1,84 +0,0 @@ -logger = require "logger-sharelatex" -metrics = require "metrics-sharelatex" -MessageManager = require "./MessageManager" -MessageFormatter = require "./MessageFormatter" -SocketManager = require "../Sockets/SocketManager" -AuthorizationManager = require "../Authorization/AuthorizationManager" - - -module.exports = MessageController = - DEFAULT_MESSAGE_LIMIT: 50 - - sendMessage: (client, data, callback = (error) ->) -> - content = data?.message?.content - room_id = data?.room?.id - return callback("malformed message") if not (content? and room_id?) - - client.get "id", (error, user_id) -> - logger.log user_id: user_id, room_id: room_id, "sending message" - AuthorizationManager.canClientSendMessageToRoom client, room_id, (error, authorized) -> - if error? - logger.err err:error, user_id:user_id, "something went wrong checking if canClientSendMessageToRoom" - return callback("something went wrong") - if authorized - SocketManager.getClientAttributes client, ["id"], (error, values) -> - if error? - logger.err err:error, user_id:user_id, "something went wrong getClientAttributes" - return callback("something went wrong") - newMessageOpts = - content: content - room_id: room_id - user_id: values[0] - timestamp: Date.now() - MessageManager.createMessage newMessageOpts, (error, message) -> - if error? - logger.err err:error, user_id:user_id, "something went wrong createMessage" - return callback("something went wrong") - MessageManager.populateMessagesWithUsers [message], (error, messages) -> - if error? - logger.err err:error, user_id:user_id, "something went wrong populateMessagesWithUsers" - return callback("something went wrong") - message = MessageFormatter.formatMessageForClientSide(messages[0]) - message.room = - id: room_id - SocketManager.emitToRoom data.room.id, "messageReceived", message:message - metrics.inc "editor.instant-message" - logger.log user_id: user_id, room_id: room_id, "sent message" - callback() - else - logger.log user_id: user_id, room_id: room_id, "unauthorized attempt to send message" - callback("unknown room") - - getMessages: (client, data, callback = (error, messages) ->) -> - room_id = data?.room?.id - return callback("malformed message") if not room_id? - - client.get "id", (error, user_id) -> - logger.log user_id: user_id, room_id: room_id, "getting messages" - AuthorizationManager.canClientReadMessagesInRoom client, room_id, (error, authorized) -> - if error? - logger.err err:error, user_id:user_id, "something went canClientReadMessagesInRoom" - return callback("something went wrong") - if authorized - query = room_id: room_id - if data.before? - query.timestamp = $lt: data.before - options = - order_by: "timestamp" - sort_order: -1 - limit: data.limit || MessageController.DEFAULT_MESSAGE_LIMIT - MessageManager.getMessages query, options, (error, messages) -> - if error? - logger.err err:error, user_id:user_id, "something went getMessages" - return callback("something went wrong") - MessageManager.populateMessagesWithUsers messages, (error, messages) -> - if error? - logger.err err:error, user_id:user_id, "something went populateMessagesWithUsers" - return callback("something went wrong") - messages = MessageFormatter.formatMessagesForClientSide messages - logger.log user_id: user_id, room_id: room_id, "got messages" - callback null, messages - else - logger.log user_id: user_id, room_id: room_id, "unauthorized attempt to get messages" - callback("unknown room") - diff --git a/services/chat/app/coffee/Features/Rooms/RoomController.coffee b/services/chat/app/coffee/Features/Rooms/RoomController.coffee deleted file mode 100644 index 015cff19ad..0000000000 --- a/services/chat/app/coffee/Features/Rooms/RoomController.coffee +++ /dev/null @@ -1,101 +0,0 @@ -async = require "async" -logger = require "logger-sharelatex" -AuthorizationManager = require "../Authorization/AuthorizationManager" -RoomManager = require "../Rooms/RoomManager" -SocketManager = require "../Sockets/SocketManager" - -module.exports = RoomController = - joinRoom: (client, data, callback = (error) ->) -> - if !data.room?.project_id? - return callback("unknown room") - project_id = data.room.project_id - - client.get "id", (error, id) -> - logger.log user_id: id, project_id: project_id, "joining room" - AuthorizationManager.canClientJoinProjectRoom client, project_id, (error, authorized) -> - return callback("something went wrong") if error? - if authorized - RoomManager.findOrCreateRoom project_id: project_id, (error, room) -> - return callback("something went wrong") if error? - room_id = room._id.toString() - RoomController._addClientToRoom client, room_id, (error) -> - return callback("something went wrong") if error? - RoomController._getClientsInRoom room_id, (error, clients) -> - return callback("something went wrong") if error? - logger.log user_id: id, project_id: project_id, room_id: room_id, "joined room" - roomDetails = - room: - id: room_id - connectedUsers: clients - callback null, roomDetails - else - logger.log user_id: id, project_id: project_id, "unauthorized attempt to join room" - callback("unknown room") - - leaveAllRooms: (client, callback = (error) ->) -> - client.get "id", (error, id) -> - logger.log user_id: id, "leaving all rooms" - SocketManager.getRoomIdsClientHasJoined client, (error, room_ids) -> - return callback("something went wrong") if error? - jobs = [] - for room_id in room_ids - do (room_id) -> - jobs.push (callback) -> - RoomController.leaveRoom client, room_id, callback - async.series jobs, (error)-> callback(error) - - leaveRoom: (client, room_id, callback = (error) ->) -> - client.get "id", (error, id) -> - logger.log user_id: id, room_id: room_id, "leaving room" - RoomController._getClientAttributes client, (error, attributes) -> - return callback("something went wrong") if error? - SocketManager.removeClientFromRoom client, room_id, (error) -> - return callback("something went wrong") if error? - leftRoomUpdate = - room: - id: room_id - user: attributes - SocketManager.emitToRoom room_id, "userLeft", leftRoomUpdate - logger.log user_id: id, room_id: room_id, "left room" - callback() - - _addClientToRoom: (client, room_id, callback = (error) ->) -> - RoomController._getClientAttributes client, (error, attributes) -> - return callback(error) if error? - update = - room: - id: room_id - user: attributes - SocketManager.emitToRoom room_id, "userJoined", update - SocketManager.addClientToRoom client, room_id, callback - - _getClientsInRoom: (room_id, callback = (error, clients) ->) -> - SocketManager.getClientsInRoom room_id, (error, clients) -> - return callback(error) if error? - formattedClients = [] - jobs = [] - - for client in clients - do (client) -> - jobs.push (callback) -> - RoomController._getClientAttributes client, (error, attributes) -> - return callback(error) if error? - formattedClients.push attributes - callback() - - async.series jobs, (error) -> - return callback(error) if error? - callback null, formattedClients - - _getClientAttributes: (client, callback = (error, attributes) ->) -> - SocketManager.getClientAttributes client, ["id", "first_name", "last_name", "email", "gravatar_url"], (error, attributes) -> - return callback(error) if error? - [id, first_name, last_name, email, gravatar_url] = attributes - clientAttributes = - id : id - first_name : first_name - last_name : last_name - email : email - gravatar_url : gravatar_url - callback null, clientAttributes - diff --git a/services/chat/app/coffee/Features/Sockets/RealTimeEventManager.coffee b/services/chat/app/coffee/Features/Sockets/RealTimeEventManager.coffee deleted file mode 100644 index eec636252f..0000000000 --- a/services/chat/app/coffee/Features/Sockets/RealTimeEventManager.coffee +++ /dev/null @@ -1,25 +0,0 @@ -settings = require 'settings-sharelatex' -rclientPub = require("redis").createClient(settings.redis.web.port, settings.redis.web.host) -rclientPub.auth(settings.redis.web.password) -rclientSub = require("redis").createClient(settings.redis.web.port, settings.redis.web.host) -rclientSub.auth(settings.redis.web.password) - -module.exports = RealTimeEventManager = - - rclientPub:rclientPub - rclientSub:rclientSub - - emitToRoom: (room_id, message, payload...) -> - RealTimeEventManager.rclientPub.publish "chat-events", JSON.stringify - room_id: room_id - message: message - payload: payload - - listenForChatEvents: () -> - @rclientSub.subscribe "chat-events" - @rclientSub.on "message", @_processEditorEvent.bind(@) - - _processEditorEvent: (channel, message) -> - io = require('../../server').io - message = JSON.parse(message) - io.sockets.in(message.room_id).emit(message.message, message.payload...) \ No newline at end of file diff --git a/services/chat/app/coffee/Features/Sockets/SocketManager.coffee b/services/chat/app/coffee/Features/Sockets/SocketManager.coffee deleted file mode 100644 index cb70fb1195..0000000000 --- a/services/chat/app/coffee/Features/Sockets/SocketManager.coffee +++ /dev/null @@ -1,40 +0,0 @@ -async = require "async" -RealTimeEventManager = require("./RealTimeEventManager") - -module.exports = SocketManager = - addClientToRoom: (client, room_id, callback = (error) ->) -> - client.join(room_id) - callback() - - removeClientFromRoom: (client, room_id, callback = (error) ->) -> - client.leave(room_id) - callback() - - getClientAttributes: (client, attributes, callback = (error, values) ->) -> - jobs = [] - for attribute in attributes - do (attribute) -> - jobs.push (cb) -> client.get attribute, cb - async.series jobs, callback - - emitToRoom: RealTimeEventManager.emitToRoom - - isClientInRoom: (targetClient, room_id, callback = (error, inRoom) ->) -> - io = require("../../server").io - for client in io.sockets.clients(room_id) - if client.id == targetClient.id - return callback null, true - callback null, false - - getClientsInRoom: (room_id, callback = (error, clients) ->) -> - io = require("../../server").io - callback null, io.sockets.clients(room_id) - - getRoomIdsClientHasJoined: (client, callback = (error, room_ids) ->) -> - io = require("../../server").io - room_ids = [] - for room_id, value of io.sockets.manager.roomClients[client.id] - if room_id[0] == "/" - room_ids.push room_id.slice(1) - callback null, room_ids - diff --git a/services/chat/app/coffee/Features/Users/UserFormatter.coffee b/services/chat/app/coffee/Features/Users/UserFormatter.coffee index 1d703a45c1..87af9b8d5d 100644 --- a/services/chat/app/coffee/Features/Users/UserFormatter.coffee +++ b/services/chat/app/coffee/Features/Users/UserFormatter.coffee @@ -2,6 +2,7 @@ crypto = require "crypto" module.exports = UserFormatter = formatUserForClientSide: (user) -> + return null if !user? if user._id? user.id = user._id.toString() delete user._id diff --git a/services/chat/app/coffee/Features/WebApi/WebApiManager.coffee b/services/chat/app/coffee/Features/WebApi/WebApiManager.coffee index 38a44ea19c..9f3960d612 100644 --- a/services/chat/app/coffee/Features/WebApi/WebApiManager.coffee +++ b/services/chat/app/coffee/Features/WebApi/WebApiManager.coffee @@ -16,14 +16,16 @@ module.exports = WebApiManager = options.method = method request options, (error, response, body) -> return callback(error) if error? - try - result = JSON.parse(body) - catch e - return callback(e) - return callback null, result - - getUserDetailsFromAuthToken: (auth_token, callback = (error, details) ->) -> - @apiRequest "/user/personal_info?auth_token=#{auth_token}", "get", callback + if 200 <= response.statusCode < 300 + try + result = JSON.parse(body) + catch e + return callback(e) + return callback null, result + else + error = new Error("web api returned non-success code: #{response.statusCode}") + error.statusCode = response.statusCode + return callback error getUserDetails: (user_id, callback = (error, details) ->) -> @apiRequest "/user/#{user_id}/personal_info", "get", { @@ -31,7 +33,11 @@ module.exports = WebApiManager = user: Settings.apis.web.user pass: Settings.apis.web.pass sendImmediately: true - }, callback - - getProjectCollaborators: (project_id, auth_token, callback = (error, collaborators) ->) -> - @apiRequest "/project/#{project_id}/collaborators?auth_token=#{auth_token}", "get", callback + }, (error, data) -> + if error? + if error.statusCode == 404 + return callback null, null + else + return callback error + else + return callback null, data diff --git a/services/chat/app/coffee/router.coffee b/services/chat/app/coffee/router.coffee index 36deca62d1..7e19ec62c5 100644 --- a/services/chat/app/coffee/router.coffee +++ b/services/chat/app/coffee/router.coffee @@ -1,31 +1,12 @@ -AuthenticationController = require("./Features/Authentication/AuthenticationController") -MessageController = require("./Features/Messages/MessageController") -RoomController = require("./Features/Rooms/RoomController") MessageHttpController = require('./Features/Messages/MessageHttpController') module.exports = Router = - route: (app, io) -> - + route: (app) -> app.get "/room/:project_id/messages", MessageHttpController.getMessages app.post "/room/:project_id/messages", MessageHttpController.sendMessage app.get "/status", (req, res, next) -> res.send("chat is alive") - io.sockets.on "connection", (client) -> - client.on "disconnect", () -> - RoomController.leaveAllRooms(client) - - client.on "auth", (data, callback = (error) ->) -> - AuthenticationController.authClient(client, data, callback) - - client.on "joinRoom", (data, callback = (error) ->) -> - RoomController.joinRoom(client, data, callback) - - client.on "sendMessage", (data, callback = (error) ->) -> - MessageController.sendMessage(client, data, callback) - - client.on "getMessages", (data, callback = (error) ->) -> - MessageController.getMessages(client, data, callback) diff --git a/services/chat/app/coffee/server.coffee b/services/chat/app/coffee/server.coffee index cbf6aeb6ac..dfac228bdd 100644 --- a/services/chat/app/coffee/server.coffee +++ b/services/chat/app/coffee/server.coffee @@ -6,16 +6,13 @@ Path = require("path") express = require("express") app = express() server = require("http").createServer(app) -io = require("socket.io").listen(server) -io.set("resource", "/chat/socket.io") -io.set("log level", 1) Router = require "./router" metrics.mongodb.monitor(Path.resolve(__dirname + "/../../node_modules/mongojs/node_modules/mongodb"), logger) app.use express.bodyParser() app.use metrics.http.monitor(logger) -Router.route(app, io) +Router.route(app) if (app.get 'env') == 'development' console.log "Development Enviroment" @@ -39,13 +36,9 @@ app.use (req, res, next) -> app.use(express.static(__dirname + "/../../public/build")) - - module.exports = { server: server - io: io app: app } -require("./Features/Sockets/RealTimeEventManager").listenForChatEvents() diff --git a/services/chat/package.json b/services/chat/package.json index 1f75d41c81..bff540a7c0 100644 --- a/services/chat/package.json +++ b/services/chat/package.json @@ -8,15 +8,14 @@ }, "dependencies": { "async": "0.2.9", + "coffee-script": "~1.7.1", "express": "3.3.1", - "request": "2.21.0", - "socket.io": "0.9.14", - "settings-sharelatex": "git+https://github.com/sharelatex/settings-sharelatex.git#v1.0.0", "logger-sharelatex": "git+https://github.com/sharelatex/logger-sharelatex.git#master", "metrics-sharelatex": "git+https://github.com/sharelatex/metrics-sharelatex.git#v1.0.0", "mongojs": "0.18.2", "redis": "~0.10.1", - "coffee-script": "~1.7.1" + "request": "^2.79.0", + "settings-sharelatex": "git+https://github.com/sharelatex/settings-sharelatex.git#v1.0.0" }, "devDependencies": { "bunyan": "^1.0.0", diff --git a/services/chat/test/acceptance/coffee/GettingMessagesTests.coffee b/services/chat/test/acceptance/coffee/GettingMessagesTests.coffee new file mode 100644 index 0000000000..b5cf30ac0d --- /dev/null +++ b/services/chat/test/acceptance/coffee/GettingMessagesTests.coffee @@ -0,0 +1,73 @@ +{ObjectId} = require "../../../app/js/mongojs" +expect = require("chai").expect +async = require "async" +crypto = require "crypto" + +MockWebApi = require "./helpers/MockWebApi" +ChatClient = require "./helpers/ChatClient" + +describe "Getting messages", -> + before -> + @user_id1 = ObjectId().toString() + @user_id2 = ObjectId().toString() + @content1 = "foo bar" + @content2 = "hello world" + MockWebApi.addUser @user_id1, @user1 = { + id: @user_id1 + first_name: "Jane" + last_name: "Smith" + email: "jane@example.com" + } + MockWebApi.addUser @user_id2, @user2 = { + id: @user_id2 + first_name: "John" + last_name: "Doe" + email: "john@example.com" + } + + describe "normally", -> + before (done) -> + @project_id = ObjectId().toString() + async.series [ + (cb) => ChatClient.sendMessage @project_id, @user_id1, @content1, cb + (cb) => ChatClient.sendMessage @project_id, @user_id2, @content2, cb + ], done + + it "should contain the messages and populated users when getting the messages", (done) -> + ChatClient.getMessages @project_id, (error, response, messages) => + expect(messages.length).to.equal 2 + messages.reverse() + expect(messages[0].content).to.equal @content1 + expect(messages[0].user).to.deep.equal { + id: @user_id1 + first_name: "Jane" + last_name: "Smith" + email: "jane@example.com" + gravatar_url: "//www.gravatar.com/avatar/#{crypto.createHash("md5").update("jane@example.com").digest("hex")}" + } + expect(messages[1].content).to.equal @content2 + expect(messages[1].user).to.deep.equal { + id: @user_id2 + first_name: "John" + last_name: "Doe" + email: "john@example.com" + gravatar_url: "//www.gravatar.com/avatar/#{crypto.createHash("md5").update("john@example.com").digest("hex")}" + } + done() + + describe "when a user doesn't exit", -> + before (done) -> + @project_id = ObjectId().toString() + @user_id3 = ObjectId().toString() + async.series [ + (cb) => ChatClient.sendMessage @project_id, @user_id3, @content1, cb + (cb) => ChatClient.sendMessage @project_id, @user_id2, @content2, cb + ], done + + it "should just return null for the user", (done) -> + ChatClient.getMessages @project_id, (error, response, messages) => + expect(messages.length).to.equal 2 + messages.reverse() + expect(messages[0].content).to.equal @content1 + expect(messages[0].user).to.equal null + done() \ No newline at end of file diff --git a/services/chat/test/acceptance/coffee/SendingAMessageTests.coffee b/services/chat/test/acceptance/coffee/SendingAMessageTests.coffee new file mode 100644 index 0000000000..e7c7e8f08c --- /dev/null +++ b/services/chat/test/acceptance/coffee/SendingAMessageTests.coffee @@ -0,0 +1,23 @@ +{ObjectId} = require "../../../app/js/mongojs" +expect = require("chai").expect + +MockWebApi = require "./helpers/MockWebApi" +ChatClient = require "./helpers/ChatClient" + +describe "Sending a message", -> + before (done) -> + @project_id = ObjectId().toString() + @user_id = ObjectId().toString() + @content = "foo bar" + ChatClient.sendMessage @project_id, @user_id, @content, (error, response, body) -> + expect(error).to.be.null + expect(response.statusCode).to.equal 201 + done() + + it "should then list the message in project messages", (done) -> + ChatClient.getMessages @project_id, (error, response, messages) => + expect(error).to.be.null + expect(response.statusCode).to.equal 200 + expect(messages.length).to.equal 1 + expect(messages[0].content).to.equal @content + done() diff --git a/services/chat/test/acceptance/coffee/helpers/ChatClient.coffee b/services/chat/test/acceptance/coffee/helpers/ChatClient.coffee new file mode 100644 index 0000000000..8be9412fa7 --- /dev/null +++ b/services/chat/test/acceptance/coffee/helpers/ChatClient.coffee @@ -0,0 +1,16 @@ +request = require("request").defaults({baseUrl: "http://localhost:3010"}) + +module.exports = + sendMessage: (project_id, user_id, content, callback) -> + request.post { + url: "/room/#{project_id}/messages" + json: + user_id: user_id + content: content + }, callback + + getMessages: (project_id, callback) -> + request.get { + url: "/room/#{project_id}/messages", + json: true + }, callback \ No newline at end of file diff --git a/services/chat/test/acceptance/coffee/helpers/MockWebApi.coffee b/services/chat/test/acceptance/coffee/helpers/MockWebApi.coffee new file mode 100644 index 0000000000..12d9c4f243 --- /dev/null +++ b/services/chat/test/acceptance/coffee/helpers/MockWebApi.coffee @@ -0,0 +1,27 @@ +express = require("express") +app = express() + +module.exports = MockWebApi = + users: {} + + addUser: (user_id, user) -> + @users[user_id] = user + + getUser: (user_id, callback = (error, user) ->) -> + return callback null, @users[user_id] + + run: () -> + app.get "/user/:user_id/personal_info", (req, res, next) => + @getUser req.params.user_id, (error, user) -> + if error? + res.send 500 + else if user? + res.send JSON.stringify user + else + res.send 404 + + app.listen 3000, (error) -> + throw error if error? + +MockWebApi.run() + diff --git a/services/chat/test/unit/coffee/Authentication/AuthenticationControllerTests.coffee b/services/chat/test/unit/coffee/Authentication/AuthenticationControllerTests.coffee deleted file mode 100644 index d9457e183f..0000000000 --- a/services/chat/test/unit/coffee/Authentication/AuthenticationControllerTests.coffee +++ /dev/null @@ -1,71 +0,0 @@ -sinon = require('sinon') -chai = require('chai') -should = chai.should() -expect = chai.expect -modulePath = "../../../../app/js/Features/Authentication/AuthenticationController.js" -SandboxedModule = require('sandboxed-module') - -describe "AuthenticationController", -> - beforeEach -> - @AuthenticationController = SandboxedModule.require modulePath, requires: - "../WebApi/WebApiManager": @WebApiManager = {} - "../Users/UserFormatter": @UserFormatter = {} - "logger-sharelatex": @logger = { log: sinon.stub() } - @callback = sinon.stub() - - describe "authClient", -> - beforeEach -> - @auth_token = "super-secret-auth-token" - @client = - params: {} - set: (key, value, callback) -> - @params[key] = value - callback() - @user = - id: "user-id-123" - email: "doug@sharelatex.com" - first_name: "Douglas" - last_name: "Adams" - @WebApiManager.getUserDetailsFromAuthToken = sinon.stub().callsArgWith(1, null, @user) - @UserFormatter.formatUserForClientSide = sinon.stub().returns({ - id: @user.id - first_name: @user.first_name - last_name: @user.last_name - email: @user.email - gravatar_url: "//gravatar/url" - }) - @AuthenticationController.authClient(@client, auth_token: @auth_token, @callback) - - it "should get the user's data from the web api", -> - @WebApiManager.getUserDetailsFromAuthToken - .calledWith(@auth_token) - .should.equal true - - it "should set the user's data and auth_token on the client object", -> - @client.params.should.deep.equal { - id: @user.id - first_name: @user.first_name - last_name: @user.last_name - email: @user.email - gravatar_url: "//gravatar/url" - auth_token: @auth_token - } - - it "should call the callback with the user details (including the gravatar URL, but not the auth_token)", -> - @callback - .calledWith(null, { - id: @user.id - email: @user.email - first_name: @user.first_name - last_name: @user.last_name - gravatar_url: "//gravatar/url" - }).should.equal true - - it "should log the request", -> - @logger.log - .calledWith(auth_token: @auth_token, "authenticating user") - .should.equal true - @logger.log - .calledWith(user: @user, auth_token: @auth_token, "authenticated user") - .should.equal true - diff --git a/services/chat/test/unit/coffee/Authorization/AuthorizationManagerTests.coffee b/services/chat/test/unit/coffee/Authorization/AuthorizationManagerTests.coffee deleted file mode 100644 index 8f2f76716c..0000000000 --- a/services/chat/test/unit/coffee/Authorization/AuthorizationManagerTests.coffee +++ /dev/null @@ -1,55 +0,0 @@ -sinon = require('sinon') -chai = require('chai') -should = chai.should() -expect = chai.expect -modulePath = "../../../../app/js/Features/Authorization/AuthorizationManager.js" -SandboxedModule = require('sandboxed-module') -events = require "events" - -describe "AuthorizationManager", -> - beforeEach -> - @SocketManager = {} - @AuthorizationManager = SandboxedModule.require modulePath, requires: - "../WebApi/WebApiManager": @WebApiManager = {} - "../Sockets/SocketManager": @SocketManager - @callback = sinon.stub() - @user_id = "user-id-123" - @project_id = "project-id-456" - @auth_token = "auth-token-789" - @client = - params: {} - get: (key, callback = (error, value) ->) -> - callback null, @params[key] - - describe "canClientJoinProjectRoom", -> - beforeEach -> - @client.params.auth_token = @auth_token - @client.params.id = @user_id - - describe "when the client is a collaborator", -> - beforeEach -> - @collaborators = [ - id: @user_id - ] - @WebApiManager.getProjectCollaborators = sinon.stub().callsArgWith(2, null, @collaborators) - @AuthorizationManager.canClientJoinProjectRoom(@client, @project_id, @callback) - - it "should get the list of collaborators from the web api", -> - @WebApiManager.getProjectCollaborators - .calledWith(@project_id, @auth_token) - .should.equal true - - it "should return true", -> - @callback.calledWith(null, true).should.equal true - - describe "when the client is not a collaborator", -> - beforeEach -> - @collaborators = [ - id: "not the user id" - ] - @WebApiManager.getProjectCollaborators = sinon.stub().callsArgWith(2, null, @collaborators) - @AuthorizationManager.canClientJoinProjectRoom(@client, @project_id, @callback) - - it "should return false", -> - @callback.calledWith(null, false).should.equal true - diff --git a/services/chat/test/unit/coffee/Messages/MessageControllerTests.coffee b/services/chat/test/unit/coffee/Messages/MessageControllerTests.coffee deleted file mode 100644 index 4b7afa2e7d..0000000000 --- a/services/chat/test/unit/coffee/Messages/MessageControllerTests.coffee +++ /dev/null @@ -1,187 +0,0 @@ -sinon = require('sinon') -chai = require('chai') -should = chai.should() -expect = chai.expect -modulePath = "../../../../app/js/Features/Messages/MessageController.js" -SandboxedModule = require('sandboxed-module') -events = require "events" -tk = require "timekeeper" -ObjectId = require("mongojs").ObjectId - -describe "MessageController", -> - beforeEach -> - tk.freeze(new Date()) - @MessageController = SandboxedModule.require modulePath, requires: - "./MessageManager": @MessageManager = {} - "./MessageFormatter": @MessageFormatter = {} - "../Sockets/SocketManager": @SocketManager = {} - "../Authorization/AuthorizationManager": @AuthorizationManager = {} - "logger-sharelatex": @logger = { log: sinon.stub() } - "metrics-sharelatex": @metrics = {inc: sinon.stub()} - @callback = sinon.stub() - @client = - params: - id: @user_id = "user-id-123" - first_name: @first_name = "Douglas" - last_name: @last_name = "Adams" - email: @email = "doug@sharelatex.com" - gravatar_url: @gravatar_url = "//gravatar/url" - get: (key, callback = (error, value) ->) -> callback null, @params[key] - - afterEach -> - tk.reset() - - describe "sendMessage", -> - beforeEach -> - @MessageManager.createMessage = sinon.stub().callsArg(1) - @SocketManager.emitToRoom = sinon.stub() - @singlePopulatedMessage = {data:"here"} - @formattedMessage = {formatted:true} - @MessageFormatter.formatMessageForClientSide = sinon.stub().returns(@formattedMessage) - @MessageManager.populateMessagesWithUsers = sinon.stub().callsArgWith(1, null, [@singlePopulatedMessage]) - @SocketManager.getClientAttributes = (client, attributes, callback) -> - values = (client.params[key] for key in attributes) - callback null, values - - describe "when the client is authorized to send a message to the room", -> - beforeEach -> - @AuthorizationManager.canClientSendMessageToRoom = sinon.stub().callsArgWith(2, null, true) - @MessageController.sendMessage(@client, { - message: - content: @content = "Hello world" - room: - id: @room_id = "room-id-123" - }, @callback) - - it "should check that the client can send a message to the room", -> - @AuthorizationManager.canClientSendMessageToRoom - .calledWith(@client, @room_id) - .should.equal true - - it "should insert the message into the database", -> - @MessageManager.createMessage - .calledWith({ - content: @content - user_id: @user_id - room_id: @room_id - timestamp: Date.now() - }) - .should.equal true - - - it "should format the message for the client", -> - @MessageFormatter.formatMessageForClientSide.calledWith(@singlePopulatedMessage).should.equal true - - it "should send the formatted message out to the other clients in the room", -> - @SocketManager.emitToRoom.calledWith(@room_id, "messageReceived", message:@formattedMessage).should.equal true - - it "should record the message as a metric", -> - @metrics.inc - .calledWith("editor.instant-message") - .should.equal true - - it "should call the callback", -> - @callback.called.should.equal true - - describe "when the client is not authorized", -> - beforeEach -> - @AuthorizationManager.canClientSendMessageToRoom = sinon.stub().callsArgWith(2, null, false) - @MessageController.sendMessage(@client, { - message: - content: @content = "Hello world" - room: - id: @room_id = "room-id-123" - }, @callback) - - it "should not insert the message into the database", -> - @MessageManager.createMessage.called.should.equal false - - it "should not send the message out to the other clients in the room", -> - @SocketManager.emitToRoom.called.should.equal false - - it "should call the callback with an error that doesn't give anything away", -> - @callback.calledWith("unknown room").should.equal true - - describe "getMessage", -> - beforeEach -> - @room_id = "room-id-123" - @timestamp = Date.now() - @limit = 42 - - describe "when the client is authorized", -> - beforeEach -> - @messages = "messages without users stub" - @messagesWithUsers = "messages with users stub" - @formattedMessages = "formatted messages stub" - @MessageManager.getMessages = sinon.stub().callsArgWith(2, null, @messages) - @MessageManager.populateMessagesWithUsers = sinon.stub().callsArgWith(1, null, @messagesWithUsers) - @AuthorizationManager.canClientReadMessagesInRoom = sinon.stub().callsArgWith(2, null, true) - @MessageFormatter.formatMessagesForClientSide = sinon.stub().returns @formattedMessages - - describe "with a timestamp and limit", -> - beforeEach -> - @MessageController.getMessages(@client, { - room: - id: @room_id, - before: @timestamp, - limit: @limit - }, @callback) - - it "should get the requested messages", -> - @MessageManager.getMessages - .calledWith({ - timestamp: $lt: @timestamp - room_id: @room_id - }, { - limit: @limit - order_by: "timestamp" - sort_order: -1 - }) - .should.equal true - - it "should populate the messages with the users", -> - @MessageManager.populateMessagesWithUsers - .calledWith(@messages) - .should.equal true - - it "should return the formatted messages", -> - @MessageFormatter.formatMessagesForClientSide - .calledWith(@messagesWithUsers) - .should.equal true - - it "should call the callback with the formatted messages", -> - @callback - .calledWith(null, @formattedMessages) - .should.equal true - - describe "without a timestamp or limit", -> - beforeEach -> - @MessageController.getMessages(@client, { - room: - id: @room_id, - }, @callback) - - it "should get a default number of messages from the beginning", -> - @MessageManager.getMessages - .calledWith({ - room_id: @room_id - }, { - limit: @MessageController.DEFAULT_MESSAGE_LIMIT - order_by: "timestamp" - sort_order: -1 - }) - .should.equal true - - describe "when the client is not authorized", -> - beforeEach -> - @AuthorizationManager.canClientReadMessagesInRoom = sinon.stub().callsArgWith(2, null, false) - @MessageController.getMessages(@client, { - room: - id: @room_id, - before: @timestamp, - limit: @limit - }, @callback) - - it "should call the callback with an error", -> - @callback.calledWith("unknown room").should.equal true - diff --git a/services/chat/test/unit/coffee/Rooms/RoomControllerTests.coffee b/services/chat/test/unit/coffee/Rooms/RoomControllerTests.coffee deleted file mode 100644 index 987ef736aa..0000000000 --- a/services/chat/test/unit/coffee/Rooms/RoomControllerTests.coffee +++ /dev/null @@ -1,240 +0,0 @@ -sinon = require('sinon') -chai = require('chai') -should = chai.should() -expect = chai.expect -modulePath = "../../../../app/js/Features/Rooms/RoomController.js" -SandboxedModule = require('sandboxed-module') -events = require "events" -ObjectId = require("mongojs").ObjectId - -class MockClient - params: {} - get: (key, callback = (error, value) ->) -> - callback null, @params[key] - -describe "RoomController", -> - beforeEach -> - @SocketManager = - getClientAttributes: sinon.stub() - - - @RoomController = SandboxedModule.require modulePath, requires: - "../Authorization/AuthorizationManager": @AuthorizationManager = {} - "../Sockets/SocketManager": @SocketManager - "../Rooms/RoomManager": @RoomManager = {} - "logger-sharelatex": @logger = { log: sinon.stub() } - - - @project_id = ObjectId().toString() - @room_id = ObjectId().toString() - @room = - _id: ObjectId(@room_id) - project_id: ObjectId(@project_id) - @callback = sinon.stub() - @client = - params: {} - get: (key, callback = (error, value) ->) -> callback null, @params[key] - - describe "joinRoom", -> - describe "when the client is authorized", -> - beforeEach -> - @AuthorizationManager.canClientJoinProjectRoom = sinon.stub().callsArgWith(2, null, true) - @RoomManager.findOrCreateRoom = sinon.stub().callsArgWith(1, null, @room) - @RoomController._addClientToRoom = sinon.stub().callsArg(2) - @RoomController._getClientsInRoom = sinon.stub().callsArgWith(1, null, @clients = ["client1", "client2"]) - @RoomController.joinRoom @client, { room: project_id: @project_id }, @callback - - it "should check that the client can join the room", -> - @AuthorizationManager.canClientJoinProjectRoom - .calledWith(@client, @project_id) - .should.equal true - - it "should ensure that the room exists", -> - @RoomManager.findOrCreateRoom - .calledWith({ project_id: @project_id }) - .should.equal true - - it "should put the client into the room", -> - @RoomController._addClientToRoom - .calledWith(@client, @room_id) - .should.equal true - - it "should get the clients already in the room", -> - @RoomController._getClientsInRoom - .calledWith(@room_id) - .should.equal true - - it "should call the callback with the room id", -> - @callback.calledWith(null, { - room: - id: @room_id - connectedUsers: @clients - }).should.equal true - - describe "when the client is not authorized", -> - beforeEach -> - @AuthorizationManager.canClientJoinProjectRoom = sinon.stub().callsArgWith(2, null, false) - @RoomController._addClientToRoom = sinon.stub().callsArg(2) - @RoomController.joinRoom @client, { room: project_id: @project_id }, @callback - - it "should not put the client into the room", -> - @RoomController._addClientToRoom.called.should.equal false - - it "should call the callback with an error that gives nothing away", -> - @callback.calledWith("unknown room").should.equal true - - describe "leaveAllRooms", -> - - beforeEach -> - @client = new MockClient() - @client.params = - id: "client-1-id" - first_name: "Douglas" - last_name: "Adams" - email: "doug@sharelatex.com" - gravatar_url: "//gravatar/url/1" - @room_ids = ["room-id-1", "room-id-2"] - @SocketManager.getRoomIdsClientHasJoined = sinon.stub().callsArgWith(1, null, @room_ids) - @RoomController.leaveRoom = sinon.stub().callsArg(2) - @RoomController.leaveAllRooms @client, @callback - - it "should get the rooms the client has joined", -> - @SocketManager.getRoomIdsClientHasJoined - .calledWith(@client) - .should.equal true - - it "should leave each room", -> - for room_id in @room_ids - @RoomController.leaveRoom - .calledWith(@client, room_id) - .should.equal true - - it "should call the callback", -> - @callback.called.should.equal true - - describe "leaveRoom", -> - beforeEach -> - @client = new MockClient() - @client.params = - id: "client-1-id" - first_name: "Douglas" - last_name: "Adams" - email: "doug@sharelatex.com" - gravatar_url: "//gravatar/url/1" - @RoomController._getClientAttributes = sinon.stub().callsArgWith(1, null, @client.params) - - @SocketManager.removeClientFromRoom = sinon.stub().callsArg(2) - @SocketManager.emitToRoom = sinon.stub() - @RoomController.leaveRoom @client, @room_id, @callback - - it "should leave the room", -> - @SocketManager.removeClientFromRoom - .calledWith(@client, @room_id) - .should.equal true - - it "should tell the other clients in the room that we have left", -> - @SocketManager.emitToRoom - .calledWith(@room_id, "userLeft", { - room: - id: @room_id - user: - id : @client.params["id"] - first_name : @client.params["first_name"] - last_name : @client.params["last_name"] - email : @client.params["email"] - gravatar_url : @client.params["gravatar_url"] - }) - .should.equal true - - it "should call the callback", -> - @callback.called.should.equal true - - describe "_getClientsInRoom", -> - beforeEach -> - @client1 = new MockClient() - @client1.params = - id: "client-1-id" - first_name: "Douglas" - last_name: "Adams" - email: "doug@sharelatex.com" - gravatar_url: "//gravatar/url/1" - @client2 = new MockClient() - @client2.params = - id: "client-2-id" - first_name: "James" - last_name: "Allen" - email: "james@sharelatex.com" - gravatar_url: "//gravatar/url/2" - @clients = [ @client1, @client2 ] - callCount = 0 - - @RoomController._getClientAttributes = (ignore, cb)=> - if callCount == 0 - callCount++ - cb(null, @client1.params) - else - cb null, @client2.params - - - @SocketManager.getClientsInRoom = sinon.stub().callsArgWith(1, null, @clients) - @RoomController._getClientsInRoom(@room_id, @callback) - - it "should get the socket.io clients in the room", -> - @SocketManager.getClientsInRoom - .calledWith(@room_id) - .should.equal true - - it "should return a formatted array of clients", -> - @callback - .calledWith(null, [{ - id : @client1.params["id"] - first_name : @client1.params["first_name"] - last_name : @client1.params["last_name"] - email : @client1.params["email"] - gravatar_url : @client1.params["gravatar_url"] - }, { - id : @client2.params["id"] - first_name : @client2.params["first_name"] - last_name : @client2.params["last_name"] - email : @client2.params["email"] - gravatar_url : @client2.params["gravatar_url"] - }]) - .should.equal true - - describe "_addClientToRoom", -> - beforeEach -> - @client = new MockClient() - @client.params = - id: "client-1-id" - first_name: "Douglas" - last_name: "Adams" - email: "doug@sharelatex.com" - gravatar_url: "//gravatar/url/1" - @RoomController._getClientAttributes = sinon.stub().callsArgWith(1, null, @client.params) - @SocketManager.addClientToRoom = sinon.stub().callsArg(2) - @SocketManager.emitToRoom = sinon.stub() - @RoomController._addClientToRoom(@client, @room_id, @callback) - - it "should add the client to the room", -> - @SocketManager.addClientToRoom - .calledWith(@client, @room_id) - .should.equal true - - it "should tell the room that the client has been added", -> - @SocketManager.emitToRoom - .calledWith(@room_id, "userJoined", { - room: - id: @room_id - user: - id : @client.params["id"] - first_name : @client.params["first_name"] - last_name : @client.params["last_name"] - email : @client.params["email"] - gravatar_url : @client.params["gravatar_url"] - }) - .should.equal true - - it "should call the callback", -> - @callback.called.should.equal true - - diff --git a/services/chat/test/unit/coffee/Sockets/RealTimeEventManagerTests.coffee b/services/chat/test/unit/coffee/Sockets/RealTimeEventManagerTests.coffee deleted file mode 100644 index 11364482fb..0000000000 --- a/services/chat/test/unit/coffee/Sockets/RealTimeEventManagerTests.coffee +++ /dev/null @@ -1,75 +0,0 @@ -SandboxedModule = require('sandboxed-module') -sinon = require('sinon') -require('chai').should() -modulePath = "../../../../app/js/Features/Sockets/RealTimeEventManager.js" - -describe "RealTimeEventManager", -> - - beforeEach -> - @settings = - redis: - web: - host: "host here" - port: "port here" - password: "password here" - @RealTimeEventManager = SandboxedModule.require modulePath, requires: - "redis": - createClient: () -> - auth:-> - "../../server" : io: @io = {} - "settings-sharelatex":@settings - @RealTimeEventManager.rclientPub = publish: sinon.stub() - @RealTimeEventManager.rclientSub = - subscribe: sinon.stub() - on: sinon.stub() - - @room_id = "room-id-here" - @message = "message-to-chat-here" - @payload = ["argument one", 42] - - describe "emitToRoom", -> - beforeEach -> - @RealTimeEventManager.emitToRoom(@room_id, @message, @payload...) - - it "should publish the message to redis", -> - @RealTimeEventManager.rclientPub.publish - .calledWith("chat-events", JSON.stringify( - room_id: @room_id, - message: @message - payload: @payload - )) - .should.equal true - - describe "listenForChatEvents", -> - beforeEach -> - @RealTimeEventManager._processEditorEvent = sinon.stub() - @RealTimeEventManager.listenForChatEvents() - - it "should subscribe to the chat-events channel", -> - @RealTimeEventManager.rclientSub.subscribe - .calledWith("chat-events") - .should.equal true - - it "should process the events with _processEditorEvent", -> - @RealTimeEventManager.rclientSub.on - .calledWith("message", sinon.match.func) - .should.equal true - - describe "_processEditorEvent", -> - describe "with a designated room", -> - beforeEach -> - @io.sockets = - in: sinon.stub().returns(emit: @emit = sinon.stub()) - data = JSON.stringify - room_id: @room_id - message: @message - payload: @payload - @RealTimeEventManager._processEditorEvent("chat-events", data) - - it "should send the message to all clients in the room", -> - @io.sockets.in - .calledWith(@room_id) - .should.equal true - @emit.calledWith(@message, @payload...).should.equal true - - \ No newline at end of file From f94de710938ab389767cea597c94e129bf7fe0bb Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 14 Dec 2016 17:44:02 +0000 Subject: [PATCH 2/2] Add acceptance runner --- services/chat/Gruntfile.coffee | 6 ++++++ services/chat/package.json | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/services/chat/Gruntfile.coffee b/services/chat/Gruntfile.coffee index 304d564a74..3496569094 100644 --- a/services/chat/Gruntfile.coffee +++ b/services/chat/Gruntfile.coffee @@ -2,6 +2,11 @@ module.exports = (grunt) -> # Project configuration. grunt.initConfig + forever: + app: + options: + index: "app.js" + execute: app: src: "app.js" @@ -134,6 +139,7 @@ module.exports = (grunt) -> grunt.loadNpmTasks 'grunt-plato' grunt.loadNpmTasks 'grunt-execute' grunt.loadNpmTasks 'grunt-bunyan' + grunt.loadNpmTasks 'grunt-forever' grunt.registerTask 'compile', ['clean', 'copy', 'coffee', 'less', 'jade', 'requirejs'] diff --git a/services/chat/package.json b/services/chat/package.json index bff540a7c0..2f3b2625a3 100644 --- a/services/chat/package.json +++ b/services/chat/package.json @@ -31,12 +31,13 @@ "grunt-contrib-requirejs": "~0.4.1", "grunt-contrib-uglify": "~0.2.7", "grunt-contrib-watch": "~0.5.3", - "grunt-requirejs": "~0.4.0", - "grunt-mocha-test": "~0.8.0", "grunt-execute": "^0.2.2", + "grunt-forever": "^0.4.7", + "grunt-mocha-test": "~0.8.0", "grunt-nodemon": "~0.1.2", "grunt-notify": "~0.2.16", "grunt-plato": "~0.2.1", + "grunt-requirejs": "~0.4.0", "sandboxed-module": "", "sinon": "", "timekeeper": ""