Просмотр исходного кода

Add acceptence tests for leaving(disconnecting) from a project

James Allen 12 лет назад
Родитель
Сommit
7b275e9e0e

+ 6 - 2
services/real-time/app/coffee/Router.coffee

@@ -5,7 +5,7 @@ HttpController = require "./HttpController"
 Utils = require "./Utils"
 
 module.exports = Router =
-	_handleError: (callback, error, client, method, extraAttrs = {}) ->
+	_handleError: (callback = ((error) ->), error, client, method, extraAttrs = {}) ->
 		Utils.getClientAttributes client, ["project_id", "doc_id", "user_id"], (_, attrs) ->
 			for key, value of extraAttrs
 				attrs[key] = value
@@ -13,7 +13,6 @@ module.exports = Router =
 			attrs.err = error
 			logger.error attrs, "server side error in #{method}"
 		# Don't return raw error to prevent leaking server side info
-		console.log "CALLING CALLBACK", callback
 		return callback {message: "Something went wrong"}
 
 	configure: (app, io, session) ->
@@ -44,6 +43,11 @@ module.exports = Router =
 					else
 						callback(null, args...)
 						
+			client.on "disconnect", () ->
+				WebsocketController.leaveProject io, client, (err) ->
+					if err?
+						Router._handleError null, err, client, "leaveProject"
+						
 				
 			client.on "joinDoc", (doc_id, fromVersion, callback) ->
 				# fromVersion is optional

+ 2 - 0
services/real-time/config/settings.defaults.coffee

@@ -15,6 +15,8 @@ module.exports =
 			url: "http://localhost:3000"
 		documentupdater:
 			url: "http://localhost:3003"
+		trackchanges:
+			url: "http://localhost:3015"
 			
 	security:
 		sessionSecret: "secret-please-change"

+ 105 - 7
services/real-time/test/acceptance/coffee/LeaveProjectTests.coffee

@@ -1,16 +1,114 @@
+RealTimeClient = require "./helpers/RealTimeClient"
+MockDocUpdaterServer = require "./helpers/MockDocUpdaterServer"
+MockTrackChangesServer = require "./helpers/MockTrackChangesServer"
+FixturesManager = require "./helpers/FixturesManager"
+
+async = require "async"
+
 describe "leaveProject", ->
+	before (done) ->
+		MockDocUpdaterServer.run (error) ->
+			return done(error) if error?
+			MockTrackChangesServer.run done
+		
 	describe "with other clients in the project", ->
-		it "should emit a disconnect message to the room"
+		before (done) ->
+			async.series [
+				(cb) =>
+					FixturesManager.setUpProject {
+						privilegeLevel: "owner"
+						project: {
+							name: "Test Project"
+						}
+					}, (e, {@project_id, @user_id}) => cb()
+					
+				(cb) =>
+					@clientA = RealTimeClient.connect()
+					@clientA.on "connect", cb
+					
+				(cb) =>
+					@clientB = RealTimeClient.connect()
+					@clientB.on "connect", cb
+					
+					@clientBDisconnectMessages = []
+					@clientB.on "clientTracking.clientDisconnected", (data) =>
+						@clientBDisconnectMessages.push data
+						
+				(cb) =>
+					@clientA.emit "joinProject", project_id: @project_id, (error, @project, @privilegeLevel, @protocolVersion) =>
+						cb(error)
+							
+				(cb) =>
+					@clientB.emit "joinProject", project_id: @project_id, (error, @project, @privilegeLevel, @protocolVersion) =>
+						cb(error)
+							
+				(cb) =>
+					# leaveProject is called when the client disconnects
+					@clientA.on "disconnect", () -> cb()
+					@clientA.disconnect()
+					
+				(cb) =>
+					# The API waits a little while before flushing changes
+					setTimeout done, require("../../../app/js/WebsocketController").FLUSH_IF_EMPTY_DELAY * 2
+					
+			], done
+
+		it "should emit a disconnect message to the room", ->
+			@clientBDisconnectMessages.should.deep.equal [@clientA.socket.sessionid]
 	
-		it "should no longer list the client in connected users"
+		it "should no longer list the client in connected users", (done) ->
+			@clientB.emit "clientTracking.getConnectedUsers", (error, users) =>
+				for user in users
+					if user.client_id == @clientA.socket.sessionid
+						throw "Expected clientA to not be listed in connected users"
+				return done()
 		
-		it "should not flush the project to the document updater"
+		it "should not flush the project to the document updater", ->
+			MockDocUpdaterServer.deleteProject
+				.calledWith(@project_id)
+				.should.equal false
 		
-		it "should not flush the project in track changes"
+		it "should not flush the project in track changes", ->
+			MockTrackChangesServer.flushProject
+				.calledWith(@project_id)
+				.should.equal false
 
 	describe "with no other clients in the project", ->
-		it "should flush the project to the document updater"
-		
-		it "should flush the project in track changes"
+		before (done) ->
+			async.series [
+				(cb) =>
+					FixturesManager.setUpProject {
+						privilegeLevel: "owner"
+						project: {
+							name: "Test Project"
+						}
+					}, (e, {@project_id, @user_id}) => cb()
+					
+				(cb) =>
+					@clientA = RealTimeClient.connect()
+					@clientA.on "connect", cb
+						
+				(cb) =>
+					@clientA.emit "joinProject", project_id: @project_id, (error, @project, @privilegeLevel, @protocolVersion) =>
+						cb(error)
+							
+				(cb) =>
+					# leaveProject is called when the client disconnects
+					@clientA.on "disconnect", () -> cb()
+					@clientA.disconnect()
+					
+				(cb) =>
+					# The API waits a little while before flushing changes
+					setTimeout done, require("../../../app/js/WebsocketController").FLUSH_IF_EMPTY_DELAY * 2
+			], done
+
+		it "should flush the project to the document updater", ->
+			MockDocUpdaterServer.deleteProject
+				.calledWith(@project_id)
+				.should.equal true
 		
+		it "should flush the project in track changes", ->
+			MockTrackChangesServer.flushProject
+				.calledWith(@project_id)
+				.should.equal true
 		

+ 9 - 0
services/real-time/test/acceptance/coffee/helpers/MockDocUpdaterServer.coffee

@@ -12,6 +12,8 @@ module.exports = MockDocUpdaterServer =
 			null, MockDocUpdaterServer.docs["#{project_id}:#{doc_id}"]
 		)
 		
+	deleteProject: sinon.stub().callsArg(1)
+		
 	getDocumentRequest: (req, res, next) ->
 		{project_id, doc_id} = req.params
 		{fromVersion} = req.query
@@ -19,6 +21,12 @@ module.exports = MockDocUpdaterServer =
 		MockDocUpdaterServer.getDocument project_id, doc_id, fromVersion, (error, data) ->
 			return next(error) if error?
 			res.json data
+			
+	deleteProjectRequest: (req, res, next) ->
+		{project_id} = req.params
+		MockDocUpdaterServer.deleteProject project_id, (error) ->
+			return next(error) if error?
+			res.sendStatus 204
 	
 	running: false
 	run: (callback = (error) ->) ->
@@ -26,6 +34,7 @@ module.exports = MockDocUpdaterServer =
 			return callback()
 		app = express()
 		app.get "/project/:project_id/doc/:doc_id", MockDocUpdaterServer.getDocumentRequest
+		app.delete "/project/:project_id", MockDocUpdaterServer.deleteProjectRequest
 		app.listen 3003, (error) ->
 			MockDocUpdaterServer.running = true
 			callback(error)

+ 21 - 0
services/real-time/test/acceptance/coffee/helpers/MockTrackChangesServer.coffee

@@ -0,0 +1,21 @@
+sinon = require "sinon"
+express = require "express"
+
+module.exports = MockTrackChangesServer =
+	flushProject: sinon.stub().callsArg(1)
+		
+	flushProjectRequest: (req, res, next) ->
+		{project_id} = req.params
+		MockTrackChangesServer.flushProject project_id, (error) ->
+			return next(error) if error?
+			res.sendStatus 204
+	
+	running: false
+	run: (callback = (error) ->) ->
+		if MockTrackChangesServer.running
+			return callback()
+		app = express()
+		app.post "/project/:project_id/flush", MockTrackChangesServer.flushProjectRequest
+		app.listen 3015, (error) ->
+			MockTrackChangesServer.running = true
+			callback(error)