| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- define [
- "libs/chai"
- "editor/ShareJsDoc"
- "libs/sharejs"
- "libs/sinon"
- ], (
- chai
- ShareJsDoc
- ShareJs
- ) ->
- should = chai.should()
- expect = chai.expect
- describe "ShareJsDoc", ->
- beforeEach ->
- @lines = ["hello", "world"]
- @snapshot = @lines.join("\n")
- @doc_id = "mock-doc-id"
- @version = 42
- socket: @socket =
- socket:
- sessionid: @session_id = "mock-session-id"
- connected: true
- emit: sinon.stub()
-
- sinon.spy ShareJs.Doc::, "_onMessage"
- sinon.spy ShareJs.Doc::, "on"
- sinon.spy ShareJs, "Doc"
- afterEach ->
- ShareJs.Doc::_onMessage.restore()
- ShareJs.Doc::on.restore()
- ShareJs.Doc.restore()
- describe "Creating a ShareJsDoc", ->
- beforeEach ->
- @shareJsDoc = new ShareJsDoc(@doc_id, @lines, @version, @socket)
- it "should create a new ShareJs.Doc instance", ->
- expect(@shareJsDoc._doc instanceof ShareJs.Doc).to.be.true
- it "should set the ShareJs doc connection", ->
- ShareJs.Doc
- .calledWith(@shareJsDoc.connection)
- .should.equal true
- it "should set the ShareJs doc name", ->
- ShareJs.Doc
- .calledWith(sinon.match.any, @doc_id)
- .should.equal true
- it "should set the type of the ShareJs doc to 'text'", ->
- ShareJs.Doc
- .calledWith(sinon.match.any, sinon.match.any, type: "text")
- .should.equal true
- it "should open the ShareJs doc so that it is in an active state", ->
- ShareJs.Doc::_onMessage
- .calledWith({
- open: true
- snapshot: @snapshot
- v: @version
- })
- .should.equal true
- it "should bind to the ShareJs doc events", ->
- ShareJs.Doc::on.calledWith("change").should.equal true
- ShareJs.Doc::on.calledWith("acknowledge").should.equal true
- ShareJs.Doc::on.calledWith("remoteop").should.equal true
- describe "Sending an op", ->
- describe "when the server responds", ->
- beforeEach (done) ->
- @shareJsDoc = new ShareJsDoc(@doc_id, @lines, @version, @socket)
- @shareJsDoc.submitOp @op = [p: 5, i: "foo"], () -> done()
- # Send the acknowledgement so that the callback is called
- setTimeout () =>
- @shareJsDoc.processUpdateFromServer {
- v: @version
- doc: @doc_id
- }
- , 10
- it "should send the op to the server", ->
- @socket.emit
- .calledWith("applyOtUpdate", @doc_id, {
- doc: @doc_id,
- op: @op
- v: @version
- })
- .should.equal true
- it "should update the document snapshot", ->
- @shareJsDoc.getSnapshot().should.equal "hellofoo\nworld"
- describe "when the server does not respond", ->
- beforeEach (done) ->
- @shareJsDoc = new ShareJsDoc(@doc_id, @lines, @version, @socket)
- sinon.spy @shareJsDoc, "trigger"
- @shareJsDoc.INFLIGHT_OP_TIMEOUT = 50
- @shareJsDoc.submitOp @op = [p: 5, i: "foo"]
- setTimeout () ->
- done()
- , 100
- it "should trigger an error", ->
- @shareJsDoc.trigger
- .calledWith("error", "Doc op was not acknowledged in time")
- .should.equal true
- describe "clearInflightAndPendingOps", ->
- beforeEach ->
- @shareJsDoc = new ShareJsDoc(@doc_id, @lines, @version, @socket)
- @shareJsDoc._doc.inflightOp = "mock-op-1"
- @shareJsDoc._doc.inflightCallbacks = ["mock-callback-1"]
- @shareJsDoc._doc.pendingOp = "mock-op-2"
- @shareJsDoc._doc.pendingCallbacks = ["mock-callback-2"]
-
- @shareJsDoc.clearInflightAndPendingOps()
- it "should clear any inflight or pendings ops", ->
- expect(@shareJsDoc._doc.inflightOp).to.be.null
- @shareJsDoc._doc.inflightCallbacks.should.deep.equal []
- expect(@shareJsDoc._doc.pendingOp).to.be.null
- @shareJsDoc._doc.pendingCallbacks.should.deep.equal []
- describe "flushPendingOps", ->
- beforeEach ->
- @shareJsDoc = new ShareJsDoc(@doc_id, @lines, @version, @socket)
- @shareJsDoc._doc.flush = sinon.stub()
- @shareJsDoc.flushPendingOps()
- it "should call _doc.flush", ->
- @shareJsDoc._doc.flush.called.should.equal true
- describe "updateConnectionState", ->
- beforeEach ->
- @shareJsDoc = new ShareJsDoc(@doc_id, @lines, @version, @socket)
- @shareJsDoc._doc._connectionStateChanged = sinon.stub()
- @shareJsDoc._doc.autoOpen = true
- @socket.socket.sessionid = "new-connection-id"
- @shareJsDoc.updateConnectionState "mock-state"
- it "should set autoOpen to false so that ShareJs doesn't try to send an open message", ->
- @shareJsDoc._doc.autoOpen.should.equal false
- it "should update the connection state", ->
- @shareJsDoc.connection.state.should.equal "mock-state"
- it "should notify the ShareJs doc of the state change", ->
- @shareJsDoc._doc._connectionStateChanged
- .calledWith("mock-state")
- .should.equal true
- it "should set the connection id to the latest socket id", ->
- @shareJsDoc.connection.id.should.equal "new-connection-id"
- describe "hasBufferedOps", ->
- describe "with inflight ops", ->
- beforeEach ->
- @shareJsDoc = new ShareJsDoc(@doc_id, @lines, @version, @socket)
- @shareJsDoc._doc.inflightOp = "mock-op-1"
- it "should return true", ->
- @shareJsDoc.hasBufferedOps().should.equal true
-
- describe "with pending ops", ->
- beforeEach ->
- @shareJsDoc = new ShareJsDoc(@doc_id, @lines, @version, @socket)
- @shareJsDoc._doc.pendingOp = "mock-op-1"
- it "should return true", ->
- @shareJsDoc.hasBufferedOps().should.equal true
-
- describe "with no buffered ops", ->
- beforeEach ->
- @shareJsDoc = new ShareJsDoc(@doc_id, @lines, @version, @socket)
- it "should return false", ->
- @shareJsDoc.hasBufferedOps().should.equal false
-
- describe "processUpdateFromServer", ->
- describe "successfully", ->
- beforeEach ->
- @shareJsDoc = new ShareJsDoc(@doc_id, @lines, @version, @socket)
- @shareJsDoc._doc._onMessage = sinon.stub()
- @shareJsDoc.processUpdateFromServer "mock-message"
- it "should pass the message onto the ShareJs Doc", ->
- @shareJsDoc._doc._onMessage
- .calledWith( "mock-message" )
- .should.equal true
- describe "with an error", ->
- beforeEach ->
- @shareJsDoc = new ShareJsDoc(@doc_id, @lines, @version, @socket)
- sinon.spy @shareJsDoc, "trigger"
- @shareJsDoc._doc._onMessage = sinon.stub().throws(@error = {message: "Mock error"})
- @shareJsDoc.processUpdateFromServer "mock-message"
- it "should trigger the error handler", ->
- @shareJsDoc.trigger
- .calledWith("error", @error)
- .should.equal true
- describe "with an external update", ->
- beforeEach ->
- @shareJsDoc = new ShareJsDoc(@doc_id, @lines, @version, @socket)
- @shareJsDoc._doc._onMessage = sinon.stub()
- sinon.spy @shareJsDoc, "trigger"
- @shareJsDoc.processUpdateFromServer { op: "mock-op", meta: { type: "external" } }
- it "should trigger an externalUpdate event", ->
- @shareJsDoc.trigger
- .calledWith("externalUpdate")
- .should.equal true
-
- describe "catchUp", ->
- beforeEach ->
- @shareJsDoc = new ShareJsDoc(@doc_id, @lines, @version, @socket)
- sinon.stub @shareJsDoc, "processUpdateFromServer", () ->
- @_doc.version++
- @shareJsDoc.catchUp [{
- ops: ["mock-op-1"]
- }, {
- ops: ["mock-op-2"]
- }]
-
- it "should apply each update", ->
- @shareJsDoc.processUpdateFromServer
- .calledWith({
- doc: @doc_id
- v: @version
- ops: ["mock-op-1"]
- })
- .should.equal true
- @shareJsDoc.processUpdateFromServer
- .calledWith({
- doc: @doc_id
- v: @version + 1
- ops: ["mock-op-2"]
- })
- .should.equal true
|