2019-07-19 06:58:40 -04:00
|
|
|
chai = require('chai')
|
|
|
|
should = chai.should()
|
|
|
|
sinon = require("sinon")
|
|
|
|
modulePath = "../../../app/js/RoomManager.js"
|
|
|
|
SandboxedModule = require('sandboxed-module')
|
|
|
|
|
|
|
|
describe 'RoomManager', ->
|
|
|
|
beforeEach ->
|
|
|
|
@project_id = "project-id-123"
|
2019-07-22 06:23:43 -04:00
|
|
|
@doc_id = "doc-id-456"
|
|
|
|
@other_doc_id = "doc-id-789"
|
|
|
|
@client = {namespace: {name: ''}, id: "first-client"}
|
2019-07-19 06:58:40 -04:00
|
|
|
@RoomManager = SandboxedModule.require modulePath, requires:
|
|
|
|
"settings-sharelatex": @settings = {}
|
2019-07-29 10:19:08 -04:00
|
|
|
"logger-sharelatex": @logger = { log: sinon.stub(), warn: sinon.stub(), error: sinon.stub() }
|
2019-07-24 11:25:45 -04:00
|
|
|
"metrics-sharelatex": @metrics = { gauge: sinon.stub() }
|
2019-07-22 06:23:43 -04:00
|
|
|
@RoomManager._clientsInRoom = sinon.stub()
|
2019-07-29 10:19:08 -04:00
|
|
|
@RoomManager._clientAlreadyInRoom = sinon.stub()
|
2019-07-22 06:23:43 -04:00
|
|
|
@RoomEvents = @RoomManager.eventSource()
|
2019-07-23 12:02:09 -04:00
|
|
|
sinon.spy(@RoomEvents, 'emit')
|
2019-07-24 04:52:20 -04:00
|
|
|
sinon.spy(@RoomEvents, 'once')
|
2019-07-19 06:58:40 -04:00
|
|
|
|
|
|
|
describe "joinProject", ->
|
|
|
|
|
|
|
|
describe "when the project room is empty", ->
|
|
|
|
|
2019-07-23 12:02:09 -04:00
|
|
|
beforeEach (done) ->
|
2019-07-22 06:23:43 -04:00
|
|
|
@RoomManager._clientsInRoom
|
|
|
|
.withArgs(@client, @project_id)
|
|
|
|
.onFirstCall().returns(0)
|
|
|
|
@client.join = sinon.stub()
|
2019-07-23 12:02:09 -04:00
|
|
|
@callback = sinon.stub()
|
|
|
|
@RoomEvents.on 'project-active', (id) =>
|
|
|
|
setTimeout () =>
|
|
|
|
@RoomEvents.emit "project-subscribed-#{id}"
|
|
|
|
, 100
|
|
|
|
@RoomManager.joinProject @client, @project_id, (err) =>
|
|
|
|
@callback(err)
|
|
|
|
done()
|
2019-07-22 06:23:43 -04:00
|
|
|
|
|
|
|
it "should emit a 'project-active' event with the id", ->
|
|
|
|
@RoomEvents.emit.calledWithExactly('project-active', @project_id).should.equal true
|
|
|
|
|
2019-07-23 12:02:09 -04:00
|
|
|
it "should listen for the 'project-subscribed-id' event", ->
|
|
|
|
@RoomEvents.once.calledWith("project-subscribed-#{@project_id}").should.equal true
|
|
|
|
|
|
|
|
it "should join the room using the id", ->
|
|
|
|
@client.join.calledWithExactly(@project_id).should.equal true
|
|
|
|
|
2019-07-19 06:58:40 -04:00
|
|
|
describe "when there are other clients in the project room", ->
|
|
|
|
|
2019-07-22 06:23:43 -04:00
|
|
|
beforeEach ->
|
|
|
|
@RoomManager._clientsInRoom
|
|
|
|
.withArgs(@client, @project_id)
|
|
|
|
.onFirstCall().returns(123)
|
|
|
|
.onSecondCall().returns(124)
|
|
|
|
@client.join = sinon.stub()
|
|
|
|
@RoomManager.joinProject @client, @project_id
|
|
|
|
|
|
|
|
it "should join the room using the id", ->
|
|
|
|
@client.join.called.should.equal true
|
|
|
|
|
|
|
|
it "should not emit any events", ->
|
|
|
|
@RoomEvents.emit.called.should.equal false
|
|
|
|
|
|
|
|
|
2019-07-19 06:58:40 -04:00
|
|
|
describe "joinDoc", ->
|
|
|
|
|
|
|
|
describe "when the doc room is empty", ->
|
|
|
|
|
2019-07-23 12:02:09 -04:00
|
|
|
beforeEach (done) ->
|
2019-07-22 06:23:43 -04:00
|
|
|
@RoomManager._clientsInRoom
|
|
|
|
.withArgs(@client, @doc_id)
|
|
|
|
.onFirstCall().returns(0)
|
|
|
|
@client.join = sinon.stub()
|
2019-07-23 12:02:09 -04:00
|
|
|
@callback = sinon.stub()
|
|
|
|
@RoomEvents.on 'doc-active', (id) =>
|
|
|
|
setTimeout () =>
|
|
|
|
@RoomEvents.emit "doc-subscribed-#{id}"
|
|
|
|
, 100
|
|
|
|
@RoomManager.joinDoc @client, @doc_id, (err) =>
|
|
|
|
@callback(err)
|
|
|
|
done()
|
2019-07-22 06:23:43 -04:00
|
|
|
|
|
|
|
it "should emit a 'doc-active' event with the id", ->
|
|
|
|
@RoomEvents.emit.calledWithExactly('doc-active', @doc_id).should.equal true
|
|
|
|
|
2019-07-23 12:02:09 -04:00
|
|
|
it "should listen for the 'doc-subscribed-id' event", ->
|
|
|
|
@RoomEvents.once.calledWith("doc-subscribed-#{@doc_id}").should.equal true
|
|
|
|
|
|
|
|
it "should join the room using the id", ->
|
|
|
|
@client.join.calledWithExactly(@doc_id).should.equal true
|
|
|
|
|
2019-07-19 06:58:40 -04:00
|
|
|
describe "when there are other clients in the doc room", ->
|
|
|
|
|
2019-07-22 06:23:43 -04:00
|
|
|
beforeEach ->
|
|
|
|
@RoomManager._clientsInRoom
|
|
|
|
.withArgs(@client, @doc_id)
|
|
|
|
.onFirstCall().returns(123)
|
|
|
|
.onSecondCall().returns(124)
|
|
|
|
@client.join = sinon.stub()
|
|
|
|
@RoomManager.joinDoc @client, @doc_id
|
|
|
|
|
|
|
|
it "should join the room using the id", ->
|
|
|
|
@client.join.called.should.equal true
|
|
|
|
|
|
|
|
it "should not emit any events", ->
|
|
|
|
@RoomEvents.emit.called.should.equal false
|
|
|
|
|
|
|
|
|
2019-07-19 06:58:40 -04:00
|
|
|
describe "leaveDoc", ->
|
|
|
|
|
|
|
|
describe "when doc room will be empty after this client has left", ->
|
|
|
|
|
2019-07-22 06:23:43 -04:00
|
|
|
beforeEach ->
|
2019-07-29 10:19:08 -04:00
|
|
|
@RoomManager._clientAlreadyInRoom
|
|
|
|
.withArgs(@client, @doc_id)
|
|
|
|
.returns(true)
|
2019-07-22 06:23:43 -04:00
|
|
|
@RoomManager._clientsInRoom
|
|
|
|
.withArgs(@client, @doc_id)
|
2019-07-23 12:02:09 -04:00
|
|
|
.onCall(0).returns(0)
|
2019-07-22 06:23:43 -04:00
|
|
|
@client.leave = sinon.stub()
|
|
|
|
@RoomManager.leaveDoc @client, @doc_id
|
|
|
|
|
|
|
|
it "should leave the room using the id", ->
|
|
|
|
@client.leave.calledWithExactly(@doc_id).should.equal true
|
|
|
|
|
|
|
|
it "should emit a 'doc-empty' event with the id", ->
|
|
|
|
@RoomEvents.emit.calledWithExactly('doc-empty', @doc_id).should.equal true
|
|
|
|
|
|
|
|
|
2019-07-19 06:58:40 -04:00
|
|
|
describe "when there are other clients in the doc room", ->
|
|
|
|
|
2019-07-22 06:23:43 -04:00
|
|
|
beforeEach ->
|
2019-07-29 10:19:08 -04:00
|
|
|
@RoomManager._clientAlreadyInRoom
|
|
|
|
.withArgs(@client, @doc_id)
|
|
|
|
.returns(true)
|
2019-07-22 06:23:43 -04:00
|
|
|
@RoomManager._clientsInRoom
|
|
|
|
.withArgs(@client, @doc_id)
|
2019-07-23 12:02:09 -04:00
|
|
|
.onCall(0).returns(123)
|
2019-07-22 06:23:43 -04:00
|
|
|
@client.leave = sinon.stub()
|
|
|
|
@RoomManager.leaveDoc @client, @doc_id
|
|
|
|
|
|
|
|
it "should leave the room using the id", ->
|
|
|
|
@client.leave.calledWithExactly(@doc_id).should.equal true
|
|
|
|
|
|
|
|
it "should not emit any events", ->
|
|
|
|
@RoomEvents.emit.called.should.equal false
|
|
|
|
|
2019-07-29 10:19:08 -04:00
|
|
|
describe "when the client is not in the doc room", ->
|
|
|
|
|
|
|
|
beforeEach ->
|
|
|
|
@RoomManager._clientAlreadyInRoom
|
|
|
|
.withArgs(@client, @doc_id)
|
|
|
|
.returns(false)
|
|
|
|
@RoomManager._clientsInRoom
|
|
|
|
.withArgs(@client, @doc_id)
|
|
|
|
.onCall(0).returns(0)
|
|
|
|
@client.leave = sinon.stub()
|
|
|
|
@RoomManager.leaveDoc @client, @doc_id
|
|
|
|
|
|
|
|
it "should not leave the room", ->
|
|
|
|
@client.leave.called.should.equal false
|
|
|
|
|
|
|
|
it "should not emit any events", ->
|
|
|
|
@RoomEvents.emit.called.should.equal false
|
|
|
|
|
2019-07-22 06:23:43 -04:00
|
|
|
|
2019-07-19 06:58:40 -04:00
|
|
|
describe "leaveProjectAndDocs", ->
|
|
|
|
|
2019-07-22 06:23:43 -04:00
|
|
|
describe "when the client is connected to the project and multiple docs", ->
|
|
|
|
|
|
|
|
beforeEach ->
|
|
|
|
@RoomManager._roomsClientIsIn = sinon.stub().returns [@project_id, @doc_id, @other_doc_id]
|
|
|
|
@client.join = sinon.stub()
|
|
|
|
@client.leave = sinon.stub()
|
|
|
|
|
|
|
|
describe "when this is the only client connected", ->
|
|
|
|
|
2019-07-23 12:02:09 -04:00
|
|
|
beforeEach (done) ->
|
2019-07-24 04:52:20 -04:00
|
|
|
# first call is for the join,
|
2019-07-23 12:02:09 -04:00
|
|
|
# second for the leave
|
2019-07-22 06:23:43 -04:00
|
|
|
@RoomManager._clientsInRoom
|
|
|
|
.withArgs(@client, @doc_id)
|
|
|
|
.onCall(0).returns(0)
|
2019-07-23 12:02:09 -04:00
|
|
|
.onCall(1).returns(0)
|
2019-07-22 06:23:43 -04:00
|
|
|
@RoomManager._clientsInRoom
|
|
|
|
.withArgs(@client, @other_doc_id)
|
|
|
|
.onCall(0).returns(0)
|
2019-07-23 12:02:09 -04:00
|
|
|
.onCall(1).returns(0)
|
2019-07-22 06:23:43 -04:00
|
|
|
@RoomManager._clientsInRoom
|
|
|
|
.withArgs(@client, @project_id)
|
|
|
|
.onCall(0).returns(0)
|
2019-07-23 12:02:09 -04:00
|
|
|
.onCall(1).returns(0)
|
2019-07-29 10:19:08 -04:00
|
|
|
@RoomManager._clientAlreadyInRoom
|
|
|
|
.withArgs(@client, @doc_id)
|
|
|
|
.returns(true)
|
|
|
|
.withArgs(@client, @other_doc_id)
|
|
|
|
.returns(true)
|
|
|
|
.withArgs(@client, @project_id)
|
|
|
|
.returns(true)
|
2019-07-23 12:02:09 -04:00
|
|
|
@RoomEvents.on 'project-active', (id) =>
|
|
|
|
setTimeout () =>
|
|
|
|
@RoomEvents.emit "project-subscribed-#{id}"
|
|
|
|
, 100
|
|
|
|
@RoomEvents.on 'doc-active', (id) =>
|
|
|
|
setTimeout () =>
|
|
|
|
@RoomEvents.emit "doc-subscribed-#{id}"
|
|
|
|
, 100
|
2019-07-22 06:23:43 -04:00
|
|
|
# put the client in the rooms
|
2019-07-23 12:02:09 -04:00
|
|
|
@RoomManager.joinProject @client, @project_id, () =>
|
|
|
|
@RoomManager.joinDoc @client, @doc_id, () =>
|
|
|
|
@RoomManager.joinDoc @client, @other_doc_id, () =>
|
|
|
|
# now leave the project
|
|
|
|
@RoomManager.leaveProjectAndDocs @client
|
|
|
|
done()
|
2019-07-22 06:23:43 -04:00
|
|
|
|
|
|
|
it "should leave all the docs", ->
|
|
|
|
@client.leave.calledWithExactly(@doc_id).should.equal true
|
|
|
|
@client.leave.calledWithExactly(@other_doc_id).should.equal true
|
|
|
|
|
|
|
|
it "should leave the project", ->
|
|
|
|
@client.leave.calledWithExactly(@project_id).should.equal true
|
|
|
|
|
|
|
|
it "should emit a 'doc-empty' event with the id for each doc", ->
|
|
|
|
@RoomEvents.emit.calledWithExactly('doc-empty', @doc_id).should.equal true
|
|
|
|
@RoomEvents.emit.calledWithExactly('doc-empty', @other_doc_id).should.equal true
|
|
|
|
|
|
|
|
it "should emit a 'project-empty' event with the id for the project", ->
|
|
|
|
@RoomEvents.emit.calledWithExactly('project-empty', @project_id).should.equal true
|
|
|
|
|
|
|
|
describe "when other clients are still connected", ->
|
|
|
|
|
|
|
|
beforeEach ->
|
|
|
|
@RoomManager._clientsInRoom
|
|
|
|
.withArgs(@client, @doc_id)
|
|
|
|
.onFirstCall().returns(123)
|
|
|
|
.onSecondCall().returns(122)
|
|
|
|
@RoomManager._clientsInRoom
|
|
|
|
.withArgs(@client, @other_doc_id)
|
|
|
|
.onFirstCall().returns(123)
|
|
|
|
.onSecondCall().returns(122)
|
|
|
|
@RoomManager._clientsInRoom
|
|
|
|
.withArgs(@client, @project_id)
|
|
|
|
.onFirstCall().returns(123)
|
|
|
|
.onSecondCall().returns(122)
|
2019-07-29 10:19:08 -04:00
|
|
|
@RoomManager._clientAlreadyInRoom
|
|
|
|
.withArgs(@client, @doc_id)
|
|
|
|
.returns(true)
|
|
|
|
.withArgs(@client, @other_doc_id)
|
|
|
|
.returns(true)
|
|
|
|
.withArgs(@client, @project_id)
|
|
|
|
.returns(true)
|
2019-07-22 06:23:43 -04:00
|
|
|
@RoomManager.leaveProjectAndDocs @client
|
|
|
|
|
|
|
|
it "should leave all the docs", ->
|
|
|
|
@client.leave.calledWithExactly(@doc_id).should.equal true
|
|
|
|
@client.leave.calledWithExactly(@other_doc_id).should.equal true
|
|
|
|
|
|
|
|
it "should leave the project", ->
|
|
|
|
@client.leave.calledWithExactly(@project_id).should.equal true
|
|
|
|
|
|
|
|
it "should not emit any events", ->
|
|
|
|
@RoomEvents.emit.called.should.equal false
|