Преглед изворни кода

Pull out MongoManager module and add tests

James Allen пре 12 година
родитељ
комит
de783bf5b0

+ 3 - 41
services/track-changes/app/coffee/HistoryManager.coffee

@@ -1,55 +1,17 @@
-{db, ObjectId} = require "./mongojs"
+MongoManager = require "./MongoManager"
 UpdateCompressor = require "./UpdateCompressor"
 UpdateCompressor = require "./UpdateCompressor"
 logger = require "logger-sharelatex"
 logger = require "logger-sharelatex"
-async = require "async"
 
 
 module.exports = HistoryManager =
 module.exports = HistoryManager =
-	getLastCompressedUpdate: (doc_id, callback = (error, update) ->) ->
-		db.docHistory
-			.find(doc_id: ObjectId(doc_id.toString()))
-			.sort(timestamp: -1)
-			.limit(1)
-			.toArray (error, compressedUpdates) ->
-				return callback(error) if error?
-				return callback null, compressedUpdates[0] or null
-
-	deleteCompressedUpdate: (id, callback = (error) ->) ->
-		db.docHistory.remove({ _id: ObjectId(id.toString()) }, callback)
-
-	popLastCompressedUpdate: (doc_id, callback = (error, update) ->) ->
-		HistoryManager.getLastCompressedUpdate doc_id, (error, update) ->
-			return callback(error) if error?
-			if update?
-				HistoryManager.deleteCompressedUpdate update._id, (error) ->
-					return callback(error) if error?
-					callback null, update
-			else
-				callback null, null
-
-	insertCompressedUpdates: (doc_id, updates, callback = (error) ->) ->
-		jobs = []
-		for update in updates
-			do (update) ->
-				jobs.push (callback) -> HistoryManager.insertCompressedUpdate doc_id, update, callback
-		async.series jobs, callback
-
-	insertCompressedUpdate: (doc_id, update, callback = (error) ->) ->
-		logger.log doc_id: doc_id, update: update, "inserting compressed update"
-		db.docHistory.insert {
-			doc_id: ObjectId(doc_id.toString())
-			op:     update.op
-			meta:   update.meta
-		}, callback
-
 	compressAndSaveRawUpdates: (doc_id, rawUpdates, callback = (error) ->) ->
 	compressAndSaveRawUpdates: (doc_id, rawUpdates, callback = (error) ->) ->
 		length = rawUpdates.length
 		length = rawUpdates.length
 		if length == 0
 		if length == 0
 			return callback()
 			return callback()
 
 
-		HistoryManager.popLastCompressedUpdate doc_id, (error, lastCompressedUpdate) ->
+		MongoManager.popLastCompressedUpdate doc_id, (error, lastCompressedUpdate) ->
 			return callback(error) if error?
 			return callback(error) if error?
 			compressedUpdates = UpdateCompressor.compressRawUpdates lastCompressedUpdate, rawUpdates
 			compressedUpdates = UpdateCompressor.compressRawUpdates lastCompressedUpdate, rawUpdates
-			HistoryManager.insertCompressedUpdates doc_id, compressedUpdates, (error) ->
+			MongoManager.insertCompressedUpdates doc_id, compressedUpdates, (error) ->
 				return callback(error) if error?
 				return callback(error) if error?
 				logger.log doc_id: doc_id, rawUpdatesLength: length, compressedUpdatesLength: compressedUpdates.length, "compressed doc updates"
 				logger.log doc_id: doc_id, rawUpdatesLength: length, compressedUpdatesLength: compressedUpdates.length, "compressed doc updates"
 				callback()
 				callback()

+ 40 - 0
services/track-changes/app/coffee/MongoManager.coffee

@@ -0,0 +1,40 @@
+{db, ObjectId} = require "./mongojs"
+async = require "async"
+
+module.exports = MongoManager =
+	getLastCompressedUpdate: (doc_id, callback = (error, update) ->) ->
+		db.docHistory
+			.find(doc_id: ObjectId(doc_id.toString()))
+			.sort( "meta.end_ts": -1)
+			.limit(1)
+			.toArray (error, compressedUpdates) ->
+				return callback(error) if error?
+				return callback null, compressedUpdates[0] or null
+
+	deleteCompressedUpdate: (id, callback = (error) ->) ->
+		db.docHistory.remove({ _id: ObjectId(id.toString()) }, callback)
+
+	popLastCompressedUpdate: (doc_id, callback = (error, update) ->) ->
+		MongoManager.getLastCompressedUpdate doc_id, (error, update) ->
+			return callback(error) if error?
+			if update?
+				MongoManager.deleteCompressedUpdate update._id, (error) ->
+					return callback(error) if error?
+					callback null, update
+			else
+				callback null, null
+
+	insertCompressedUpdates: (doc_id, updates, callback = (error) ->) ->
+		jobs = []
+		for update in updates
+			do (update) ->
+				jobs.push (callback) -> MongoManager.insertCompressedUpdate doc_id, update, callback
+		async.series jobs, callback
+
+	insertCompressedUpdate: (doc_id, update, callback = (error) ->) ->
+		db.docHistory.insert {
+			doc_id: ObjectId(doc_id.toString())
+			op:     update.op
+			meta:   update.meta
+			v:      update.v
+		}, callback

+ 13 - 13
services/track-changes/test/unit/coffee/HistoryManager/HistoryManagerTests.coffee

@@ -9,20 +9,20 @@ describe "HistoryManager", ->
 	beforeEach ->
 	beforeEach ->
 		@HistoryManager = SandboxedModule.require modulePath, requires:
 		@HistoryManager = SandboxedModule.require modulePath, requires:
 			"./UpdateCompressor": @UpdateCompressor = {}
 			"./UpdateCompressor": @UpdateCompressor = {}
-			"./mongojs" : {}
+			"./MongoManager" : @MongoManager = {}
 			"logger-sharelatex": { log: sinon.stub() }
 			"logger-sharelatex": { log: sinon.stub() }
 		@doc_id = "doc-id-123"
 		@doc_id = "doc-id-123"
 		@callback = sinon.stub()
 		@callback = sinon.stub()
 
 
 	describe "when there are no raw ops", ->
 	describe "when there are no raw ops", ->
 		beforeEach ->
 		beforeEach ->
-			@HistoryManager.popLastCompressedUpdate = sinon.stub()
-			@HistoryManager.insertCompressedUpdates = sinon.stub()
+			@MongoManager.popLastCompressedUpdate = sinon.stub()
+			@MongoManager.insertCompressedUpdates = sinon.stub()
 			@HistoryManager.compressAndSaveRawUpdates @doc_id, [], @callback
 			@HistoryManager.compressAndSaveRawUpdates @doc_id, [], @callback
 
 
 		it "should not need to access the database", ->
 		it "should not need to access the database", ->
-			@HistoryManager.popLastCompressedUpdate.called.should.equal false
-			@HistoryManager.insertCompressedUpdates.called.should.equal false
+			@MongoManager.popLastCompressedUpdate.called.should.equal false
+			@MongoManager.insertCompressedUpdates.called.should.equal false
 
 
 		it "should call the callback", ->
 		it "should call the callback", ->
 			@callback.called.should.equal true
 			@callback.called.should.equal true
@@ -32,13 +32,13 @@ describe "HistoryManager", ->
 			@rawUpdates = ["mock-raw-op-1", "mock-raw-op-2"]
 			@rawUpdates = ["mock-raw-op-1", "mock-raw-op-2"]
 			@compressedUpdates = ["mock-compressed-op"]
 			@compressedUpdates = ["mock-compressed-op"]
 
 
-			@HistoryManager.popLastCompressedUpdate = sinon.stub().callsArgWith(1, null, null)
-			@HistoryManager.insertCompressedUpdates = sinon.stub().callsArg(2)
+			@MongoManager.popLastCompressedUpdate = sinon.stub().callsArgWith(1, null, null)
+			@MongoManager.insertCompressedUpdates = sinon.stub().callsArg(2)
 			@UpdateCompressor.compressRawUpdates = sinon.stub().returns(@compressedUpdates)
 			@UpdateCompressor.compressRawUpdates = sinon.stub().returns(@compressedUpdates)
 			@HistoryManager.compressAndSaveRawUpdates @doc_id, @rawUpdates, @callback
 			@HistoryManager.compressAndSaveRawUpdates @doc_id, @rawUpdates, @callback
 
 
 		it "should try to pop the last compressed op", ->
 		it "should try to pop the last compressed op", ->
-			@HistoryManager.popLastCompressedUpdate
+			@MongoManager.popLastCompressedUpdate
 				.calledWith(@doc_id)
 				.calledWith(@doc_id)
 				.should.equal true
 				.should.equal true
 		
 		
@@ -48,7 +48,7 @@ describe "HistoryManager", ->
 				.should.equal true
 				.should.equal true
 		
 		
 		it "should save the compressed ops", ->
 		it "should save the compressed ops", ->
-			@HistoryManager.insertCompressedUpdates
+			@MongoManager.insertCompressedUpdates
 				.calledWith(@doc_id, @compressedUpdates)
 				.calledWith(@doc_id, @compressedUpdates)
 				.should.equal true
 				.should.equal true
 
 
@@ -61,13 +61,13 @@ describe "HistoryManager", ->
 			@lastCompressedUpdate = "mock-last-compressed-op-0"
 			@lastCompressedUpdate = "mock-last-compressed-op-0"
 			@compressedUpdates = ["mock-compressed-op-1"]
 			@compressedUpdates = ["mock-compressed-op-1"]
 
 
-			@HistoryManager.popLastCompressedUpdate = sinon.stub().callsArgWith(1, null, @lastCompressedUpdate)
-			@HistoryManager.insertCompressedUpdates = sinon.stub().callsArg(2)
+			@MongoManager.popLastCompressedUpdate = sinon.stub().callsArgWith(1, null, @lastCompressedUpdate)
+			@MongoManager.insertCompressedUpdates = sinon.stub().callsArg(2)
 			@UpdateCompressor.compressRawUpdates = sinon.stub().returns(@compressedUpdates)
 			@UpdateCompressor.compressRawUpdates = sinon.stub().returns(@compressedUpdates)
 			@HistoryManager.compressAndSaveRawUpdates @doc_id, @rawUpdates, @callback
 			@HistoryManager.compressAndSaveRawUpdates @doc_id, @rawUpdates, @callback
 
 
 		it "should try to pop the last compressed op", ->
 		it "should try to pop the last compressed op", ->
-			@HistoryManager.popLastCompressedUpdate
+			@MongoManager.popLastCompressedUpdate
 				.calledWith(@doc_id)
 				.calledWith(@doc_id)
 				.should.equal true
 				.should.equal true
 		
 		
@@ -77,7 +77,7 @@ describe "HistoryManager", ->
 				.should.equal true
 				.should.equal true
 		
 		
 		it "should save the compressed ops", ->
 		it "should save the compressed ops", ->
-			@HistoryManager.insertCompressedUpdates
+			@MongoManager.insertCompressedUpdates
 				.calledWith(@doc_id, @compressedUpdates)
 				.calledWith(@doc_id, @compressedUpdates)
 				.should.equal true
 				.should.equal true
 
 

+ 133 - 0
services/track-changes/test/unit/coffee/MongoManager/MongoManagerTests.coffee

@@ -0,0 +1,133 @@
+sinon = require('sinon')
+chai = require('chai')
+should = chai.should()
+expect = chai.expect
+modulePath = "../../../../app/js/MongoManager.js"
+SandboxedModule = require('sandboxed-module')
+{ObjectId} = require("mongojs")
+
+describe "MongoManager", ->
+	beforeEach ->
+		@MongoManager = SandboxedModule.require modulePath, requires:
+			"./mongojs" : { db: @db = {}, ObjectId: ObjectId }
+		@callback = sinon.stub()
+		@doc_id = ObjectId().toString()
+
+	describe "getLastCompressedUpdate", ->
+		beforeEach ->
+			@update = "mock-update"
+			@db.docHistory = {}
+			@db.docHistory.find = sinon.stub().returns @db.docHistory
+			@db.docHistory.sort = sinon.stub().returns @db.docHistory
+			@db.docHistory.limit = sinon.stub().returns @db.docHistory
+			@db.docHistory.toArray = sinon.stub().callsArgWith(0, null, [@update])
+
+			@MongoManager.getLastCompressedUpdate @doc_id, @callback
+
+		it "should find the updates for the doc", ->
+			@db.docHistory.find
+				.calledWith(doc_id: ObjectId(@doc_id))
+				.should.equal true
+
+		it "should limit to one result", ->
+			@db.docHistory.limit
+				.calledWith(1)
+				.should.equal true
+
+		it "should sort in descending timestamp order", ->
+			@db.docHistory.sort
+				.calledWith("meta.end_ts": -1)
+				.should.equal true
+
+		it "should call the call back with the update", ->
+			@callback.calledWith(null, @update).should.equal true
+
+	describe "deleteCompressedUpdate", ->
+		beforeEach ->
+			@update_id = ObjectId().toString()
+			@db.docHistory = 
+				remove: sinon.stub().callsArg(1)
+			@MongoManager.deleteCompressedUpdate(@update_id, @callback)
+
+		it "should remove the update", ->
+			@db.docHistory.remove
+				.calledWith(_id: ObjectId(@update_id))
+				.should.equal true
+
+		it "should call the callback", ->
+			@callback.called.should.equal true
+
+	describe "popLastCompressedUpdate", ->
+		describe "when there is no last update", ->
+			beforeEach ->
+				@MongoManager.getLastCompressedUpdate = sinon.stub().callsArgWith(1, null, null)
+				@MongoManager.deleteCompressedUpdate = sinon.stub()
+				@MongoManager.popLastCompressedUpdate @doc_id, @callback
+
+			it "should get the last update", ->
+				@MongoManager.getLastCompressedUpdate
+					.calledWith(@doc_id)
+					.should.equal true
+
+			it "should not try to delete the last update", ->
+				@MongoManager.deleteCompressedUpdate.called.should.equal false
+
+			it "should call the callback with no update", ->
+				@callback.calledWith(null, null).should.equal true
+
+		describe "when there is an update", ->
+			beforeEach ->
+				@update = { _id: Object() }
+				@MongoManager.getLastCompressedUpdate = sinon.stub().callsArgWith(1, null, @update)
+				@MongoManager.deleteCompressedUpdate = sinon.stub().callsArgWith(1, null)
+				@MongoManager.popLastCompressedUpdate @doc_id, @callback
+
+			it "should get the last update", ->
+				@MongoManager.getLastCompressedUpdate
+					.calledWith(@doc_id)
+					.should.equal true
+
+			it "should delete the last update", ->
+				@MongoManager.deleteCompressedUpdate
+					.calledWith(@update._id)
+					.should.equal true
+
+			it "should call the callback with the update", ->
+				@callback.calledWith(null, @update).should.equal true
+
+	describe "insertCompressedUpdate", ->
+		beforeEach ->
+			@update = { op: "op", meta: "meta", v: "v"}
+			@db.docHistory =
+				insert: sinon.stub().callsArg(1)
+			@MongoManager.insertCompressedUpdate @doc_id, @update, @callback
+
+		it "should insert the update", ->
+			@db.docHistory.insert
+				.calledWith({
+					doc_id: ObjectId(@doc_id),
+					op: @update.op,
+					meta: @update.meta,
+					v: @update.v
+				})
+				.should.equal true
+
+		it "should call the callback", ->
+			@callback.called.should.equal true
+
+	describe "insertCompressedUpdates", ->
+		beforeEach (done) ->
+			@updates = [ "mock-update-1", "mock-update-2" ]
+			@MongoManager.insertCompressedUpdate = sinon.stub().callsArg(2)
+			@MongoManager.insertCompressedUpdates @doc_id, @updates, (args...) =>
+				@callback(args...)
+				done()
+
+		it "should insert each update", ->
+			for update in @updates
+				@MongoManager.insertCompressedUpdate
+					.calledWith(@doc_id, update)
+					.should.equal true
+
+		it "should call the callback", ->
+			@callback.called.should.equal true