Skip to content

Commit 3259bd0

Browse files
committed
refactor(realtime): extract user event "cursor" related
1. move "cursor focus", "cursor activity", "cursor blur" event handler to SocketClient 2. add test case for that Signed-off-by: BoHong Li <[email protected]>
1 parent 8171860 commit 3259bd0

File tree

2 files changed

+106
-41
lines changed

2 files changed

+106
-41
lines changed

lib/realtime.js

Lines changed: 52 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -763,22 +763,65 @@ class SocketClient {
763763
this.socket.on('refresh', this.refreshEventHandler.bind(this))
764764
// received user status
765765
this.socket.on('user status', this.userStatusEventHandler.bind(this))
766-
767766
// when a new client disconnect
768767
this.socket.on('disconnect', this.disconnectEventHandler.bind(this))
768+
// received cursor focus
769+
this.socket.on('cursor focus', this.cursorFocusEventHandler.bind(this))
770+
// received cursor activity
771+
this.socket.on('cursor activity', this.cursorActivityEventHandler.bind(this))
772+
// received cursor blur
773+
this.socket.on('cursor blur', this.cursorBlurEventHandlder.bind(this))
774+
}
775+
776+
isNoteAndUserExists () {
777+
const note = getNoteFromNotePool(this.socket.noteId)
778+
const user = getUserFromUserPool(this.socket.id)
779+
return note && user
780+
}
769781

782+
getCurrentUser () {
783+
return getUserFromUserPool(this.socket.id)
784+
}
785+
786+
getNoteChannel () {
787+
return this.socket.broadcast.to(this.socket.noteId)
788+
}
789+
790+
cursorFocusEventHandler (data) {
791+
if (!this.isNoteAndUserExists()) return
792+
const user = this.getCurrentUser()
793+
user.cursor = data
794+
const out = buildUserOutData(user)
795+
this.getNoteChannel().emit('cursor focus', out)
796+
}
797+
798+
cursorActivityEventHandler (data) {
799+
if (!this.isNoteAndUserExists()) return
800+
const user = this.getCurrentUser()
801+
user.cursor = data
802+
const out = buildUserOutData(user)
803+
this.getNoteChannel().emit('cursor activity', out)
804+
}
805+
806+
cursorBlurEventHandlder () {
807+
if (!this.isNoteAndUserExists()) return
808+
const user = this.getCurrentUser()
809+
user.cursor = null
810+
this.getNoteChannel().emit('cursor blur', {
811+
id: this.socket.id
812+
})
770813
}
771814

772815
refreshEventHandler () {
773816
exports.emitRefresh(this.socket)
774817
}
775818

776819
userStatusEventHandler (data) {
777-
const noteId = this.socket.noteId
778-
const user = getUserFromUserPool(this.socket.id)
779-
if (!noteId || !getNoteFromNotePool(noteId) || !user) return
780-
781-
if (config.debug) { logger.info('SERVER received [' + noteId + '] user status from [' + this.socket.id + ']: ' + JSON.stringify(data)) }
820+
if (!this.isNoteAndUserExists()) return
821+
const user = this.getCurrentUser()
822+
if (config.debug) {
823+
logger.info('SERVER received [' + this.socket.noteId + '] user status from [' + this.socket.id + ']: ' + JSON.stringify(data))
824+
}
782825
if (data) {
783826
user.idle = data.idle
784827
user.type = data.type
@@ -946,7 +989,9 @@ function connection (socket) {
946989
var users = []
947990
Object.keys(notes[noteId].users).forEach(function (key) {
948991
var user = notes[noteId].users[key]
949-
if (user) { users.push(buildUserOutData(user)) }
992+
if (user) {
993+
users.push(buildUserOutData(user))
994+
}
950995
})
951996
var out = {
952997
users: users
@@ -961,38 +1006,6 @@ function connection (socket) {
9611006
minimumCompatibleVersion: config.minimumCompatibleVersion
9621007
})
9631008
})
964-
965-
// received cursor focus
966-
socket.on('cursor focus', function (data) {
967-
var noteId = socket.noteId
968-
var user = users[socket.id]
969-
if (!noteId || !notes[noteId] || !user) return
970-
user.cursor = data
971-
var out = buildUserOutData(user)
972-
socket.broadcast.to(noteId).emit('cursor focus', out)
973-
})
974-
975-
// received cursor activity
976-
socket.on('cursor activity', function (data) {
977-
var noteId = socket.noteId
978-
var user = users[socket.id]
979-
if (!noteId || !notes[noteId] || !user) return
980-
user.cursor = data
981-
var out = buildUserOutData(user)
982-
socket.broadcast.to(noteId).emit('cursor activity', out)
983-
})
984-
985-
// received cursor blur
986-
socket.on('cursor blur', function () {
987-
var noteId = socket.noteId
988-
var user = users[socket.id]
989-
if (!noteId || !notes[noteId] || !user) return
990-
user.cursor = null
991-
var out = {
992-
id: socket.id
993-
}
994-
socket.broadcast.to(noteId).emit('cursor blur', out)
995-
})
9961009
}
9971010

9981011
exports = module.exports = realtime

test/realtime.test.js

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,26 @@ const assert = require('assert')
77
const sinon = require('sinon')
88

99
function makeMockSocket (headers, query) {
10+
const broadCastChannelCache = {}
1011
return {
1112
id: Math.round(Math.random() * 10000),
1213
handshake: {
1314
headers: Object.assign({}, headers),
1415
query: Object.assign({}, query)
1516
},
16-
on: sinon.fake()
17+
on: sinon.fake(),
18+
broadCastChannelCache: {},
19+
broadcast: {
20+
to: (channel) => {
21+
if (!broadCastChannelCache[channel]) {
22+
broadCastChannelCache[channel] = {
23+
channel: channel,
24+
emit: sinon.fake()
25+
}
26+
}
27+
return broadCastChannelCache[channel]
28+
}
29+
}
1730
}
1831
}
1932

@@ -553,9 +566,48 @@ describe('realtime', function () {
553566
disconnectFunc()
554567
assert(disconnectStub.called === false)
555568
})
569+
})
570+
571+
;['cursor focus', 'cursor activity', 'cursor blur'].forEach( (event) => {
572+
describe(event, function () {
573+
let cursorFocusFunc
574+
575+
const cursorData = {
576+
cursor: 10
577+
}
578+
579+
beforeEach(() => {
580+
cursorFocusFunc = eventFuncMap.get(event)
581+
realtime.notes[noteId] = {}
582+
})
556583

584+
it('should broadcast to all client', () => {
585+
cursorFocusFunc(cursorData)
586+
const broadChannelEmitFake = clientSocket.broadcast.to(noteId).emit
587+
assert(broadChannelEmitFake.calledOnce)
588+
assert(broadChannelEmitFake.lastCall.args[0] === event)
589+
if (event === 'cursor blur') {
590+
assert(broadChannelEmitFake.lastCall.args[1].id === clientSocket.id)
591+
} else {
592+
assert.deepStrictEqual(broadChannelEmitFake.lastCall.args[1].cursor, cursorData)
593+
}
594+
})
595+
596+
it('should not broadcast when note not exists', () => {
597+
delete realtime.notes[noteId]
598+
cursorFocusFunc(cursorData)
599+
const broadChannelEmitFake = clientSocket.broadcast.to(noteId).emit
600+
assert(broadChannelEmitFake.called === false)
601+
})
602+
603+
it('should not broadcast when user not exists', () => {
604+
delete realtime.users[clientSocket.id]
605+
cursorFocusFunc(cursorData)
606+
const broadChannelEmitFake = clientSocket.broadcast.to(noteId).emit
607+
assert(broadChannelEmitFake.called === false)
608+
})
609+
})
557610
})
558611

559612
})
560-
561613
})

0 commit comments

Comments
 (0)