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 <a60814billy@gmail.com>
This commit is contained in:
BoHong Li 2019-05-03 19:40:35 +08:00
parent 8171860d47
commit 3259bd0f11
No known key found for this signature in database
GPG Key ID: 9696D5590D58290F
2 changed files with 106 additions and 41 deletions

View File

@ -763,10 +763,53 @@ class SocketClient {
this.socket.on('refresh', this.refreshEventHandler.bind(this))
// received user status
this.socket.on('user status', this.userStatusEventHandler.bind(this))
// when a new client disconnect
this.socket.on('disconnect', this.disconnectEventHandler.bind(this))
// received cursor focus
this.socket.on('cursor focus', this.cursorFocusEventHandler.bind(this))
// received cursor activity
this.socket.on('cursor activity', this.cursorActivityEventHandler.bind(this))
// received cursor blur
this.socket.on('cursor blur', this.cursorBlurEventHandlder.bind(this))
}
isNoteAndUserExists () {
const note = getNoteFromNotePool(this.socket.noteId)
const user = getUserFromUserPool(this.socket.id)
return note && user
}
getCurrentUser () {
return getUserFromUserPool(this.socket.id)
}
getNoteChannel () {
return this.socket.broadcast.to(this.socket.noteId)
}
cursorFocusEventHandler (data) {
if (!this.isNoteAndUserExists()) return
const user = this.getCurrentUser()
user.cursor = data
const out = buildUserOutData(user)
this.getNoteChannel().emit('cursor focus', out)
}
cursorActivityEventHandler (data) {
if (!this.isNoteAndUserExists()) return
const user = this.getCurrentUser()
user.cursor = data
const out = buildUserOutData(user)
this.getNoteChannel().emit('cursor activity', out)
}
cursorBlurEventHandlder () {
if (!this.isNoteAndUserExists()) return
const user = this.getCurrentUser()
user.cursor = null
this.getNoteChannel().emit('cursor blur', {
id: this.socket.id
})
}
refreshEventHandler () {
@ -774,11 +817,11 @@ class SocketClient {
}
userStatusEventHandler (data) {
const noteId = this.socket.noteId
const user = getUserFromUserPool(this.socket.id)
if (!noteId || !getNoteFromNotePool(noteId) || !user) return
if (config.debug) { logger.info('SERVER received [' + noteId + '] user status from [' + this.socket.id + ']: ' + JSON.stringify(data)) }
if (!this.isNoteAndUserExists()) return
const user = this.getCurrentUser()
if (config.debug) {
logger.info('SERVER received [' + this.socket.noteId + '] user status from [' + this.socket.id + ']: ' + JSON.stringify(data))
}
if (data) {
user.idle = data.idle
user.type = data.type
@ -946,7 +989,9 @@ function connection (socket) {
var users = []
Object.keys(notes[noteId].users).forEach(function (key) {
var user = notes[noteId].users[key]
if (user) { users.push(buildUserOutData(user)) }
if (user) {
users.push(buildUserOutData(user))
}
})
var out = {
users: users
@ -961,38 +1006,6 @@ function connection (socket) {
minimumCompatibleVersion: config.minimumCompatibleVersion
})
})
// received cursor focus
socket.on('cursor focus', function (data) {
var noteId = socket.noteId
var user = users[socket.id]
if (!noteId || !notes[noteId] || !user) return
user.cursor = data
var out = buildUserOutData(user)
socket.broadcast.to(noteId).emit('cursor focus', out)
})
// received cursor activity
socket.on('cursor activity', function (data) {
var noteId = socket.noteId
var user = users[socket.id]
if (!noteId || !notes[noteId] || !user) return
user.cursor = data
var out = buildUserOutData(user)
socket.broadcast.to(noteId).emit('cursor activity', out)
})
// received cursor blur
socket.on('cursor blur', function () {
var noteId = socket.noteId
var user = users[socket.id]
if (!noteId || !notes[noteId] || !user) return
user.cursor = null
var out = {
id: socket.id
}
socket.broadcast.to(noteId).emit('cursor blur', out)
})
}
exports = module.exports = realtime

View File

@ -7,13 +7,26 @@ const assert = require('assert')
const sinon = require('sinon')
function makeMockSocket (headers, query) {
const broadCastChannelCache = {}
return {
id: Math.round(Math.random() * 10000),
handshake: {
headers: Object.assign({}, headers),
query: Object.assign({}, query)
},
on: sinon.fake()
on: sinon.fake(),
broadCastChannelCache: {},
broadcast: {
to: (channel) => {
if (!broadCastChannelCache[channel]) {
broadCastChannelCache[channel] = {
channel: channel,
emit: sinon.fake()
}
}
return broadCastChannelCache[channel]
}
}
}
}
@ -553,9 +566,48 @@ describe('realtime', function () {
disconnectFunc()
assert(disconnectStub.called === false)
})
})
;['cursor focus', 'cursor activity', 'cursor blur'].forEach( (event) => {
describe(event, function () {
let cursorFocusFunc
const cursorData = {
cursor: 10
}
beforeEach(() => {
cursorFocusFunc = eventFuncMap.get(event)
realtime.notes[noteId] = {}
})
it('should broadcast to all client', () => {
cursorFocusFunc(cursorData)
const broadChannelEmitFake = clientSocket.broadcast.to(noteId).emit
assert(broadChannelEmitFake.calledOnce)
assert(broadChannelEmitFake.lastCall.args[0] === event)
if (event === 'cursor blur') {
assert(broadChannelEmitFake.lastCall.args[1].id === clientSocket.id)
} else {
assert.deepStrictEqual(broadChannelEmitFake.lastCall.args[1].cursor, cursorData)
}
})
it('should not broadcast when note not exists', () => {
delete realtime.notes[noteId]
cursorFocusFunc(cursorData)
const broadChannelEmitFake = clientSocket.broadcast.to(noteId).emit
assert(broadChannelEmitFake.called === false)
})
it('should not broadcast when user not exists', () => {
delete realtime.users[clientSocket.id]
cursorFocusFunc(cursorData)
const broadChannelEmitFake = clientSocket.broadcast.to(noteId).emit
assert(broadChannelEmitFake.called === false)
})
})
})
})
})