Skip to content
This repository has been archived by the owner on Nov 10, 2022. It is now read-only.

Commit

Permalink
feat: emit list-users on user update
Browse files Browse the repository at this point in the history
  • Loading branch information
severo committed Jan 22, 2020
1 parent eca2294 commit e36e426
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/domain/events/toclient/event.to.client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export class EventToClient {
// static readonly RoomGuestsList = 'room-guests-list'

// static readonly UsersList = 'users-list'
static readonly UsersList = 'users-list'

static readonly InternalServerError = 'internal-server-error'
}
2 changes: 1 addition & 1 deletion src/domain/events/toclient/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// export * from "./room.guests.list.event";

// export * from "./users.list.event";
export * from './users.list.event'

export * from './internal.server.error.event'
27 changes: 27 additions & 0 deletions src/domain/events/toclient/users.list.event.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { expect } from 'chai'
import { UsersListEvent } from './users.list.event'
import { ExportedUser } from '../../index'

describe('Events', () => {
describe('UsersListEvent', () => {
it("should have 'users-list' event as name", () => {
expect(UsersListEvent.eventName).to.equal('users-list')
})

it('should initialize exportedUsers object', () => {
// arrange
const exportedUsers: ExportedUser[] = [
{ name: 'Usain', color: '#FFFF00' },
{ name: 'Bob', color: '#333' },
]

// act
let usersList = new UsersListEvent(exportedUsers)

// assert
expect(usersList.exportedUsers).to.not.be.undefined
expect(usersList.exportedUsers).to.have.length(2)
expect(usersList.exportedUsers).to.equal(exportedUsers)
})
})
})
8 changes: 8 additions & 0 deletions src/domain/events/toclient/users.list.event.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { EventToClient } from './event.to.client'
import { ExportedUser } from '../../index'

export class UsersListEvent {
static eventName: string = EventToClient.UsersList
// TODO: send less information to the client?
constructor(public readonly exportedUsers: ExportedUser[]) {}
}
14 changes: 13 additions & 1 deletion src/domain/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import Joi from '@hapi/joi'
import nanoid from 'nanoid'
import rnd from 'randomcolor'

export interface ExportedUser {
name: string
color: string
}

// Validation
// TODO: remove, or merge, with src/shared/validation?
const nameSchema = Joi.string().min(1)
Expand Down Expand Up @@ -66,7 +71,14 @@ export class User {
this._color = checkColor(color)
}

touch() {
public export(): ExportedUser {
return {
name: this._name,
color: this._color,
}
}

public touch() {
this._updated_at = new Date()
this._expired_at = new Date(
this._updated_at.getTime() + this._msUntilExpiration
Expand Down
46 changes: 42 additions & 4 deletions src/socket.io/socket.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
UpdateUserNameEvent,
UpdateUserColorEvent,
} from '../domain/events/toserver'
import { UsersListEvent } from '../domain/events/toclient'
import { ExportedUser } from '../domain'

const socketUrl: string = 'http://localhost:5000'
const options: SocketIOClient.ConnectOpts = {
Expand All @@ -24,17 +26,25 @@ describe('Server', () => {
let server: SocketIO.Server
let socket: Socket
let client: SocketIOClient.Socket
let passiveClient: SocketIOClient.Socket
let mockLogger: MockLogger

// order of the clients in the Socket class' 'users' property
// requires the clients to be connect in that order
const ACTIVE_CLIENT_IDX = 0
const PASSIVE_CLIENT_IDX = 1

beforeEach(() => {
server = io().listen(5000)
mockLogger = new MockLogger()
socket = new Socket(server, mockLogger)
socket.connect()
client = ioClient.connect(socketUrl + '/occupapp-beta', options)
passiveClient = ioClient.connect(socketUrl + '/occupapp-beta', options)
})

afterEach(() => {
passiveClient.close()
client.close()
server.close()
})
Expand Down Expand Up @@ -122,12 +132,21 @@ describe('Server', () => {
)
})

it('should log info message for correct name, updated should be true and error should not exist', async () => {
it('should log info message for valid name, updated should be true, error should not exist, and a users-list event should be sent', async () => {
// arrange
await new Promise(resolve => passiveClient.on('connect', resolve))
const getUsersList = (): Promise<ExportedUser[]> =>
new Promise(resolve =>
passiveClient.on(UsersListEvent.eventName, resolve)
)

const args = { name: 'George' }

// act
const value = await updateNameUser(args)
const [value, list]: [
UpdateUserColorAckArgs,
ExportedUser[]
] = await Promise.all([updateNameUser(args), getUsersList()])

// assert
expect(value).to.not.be.undefined
Expand All @@ -136,6 +155,11 @@ describe('Server', () => {
mockLogger
.getInfoLogs()
.should.include.something.that.equals(`User name updated`)
expect(list).to.have.length(2)
expect(list[ACTIVE_CLIENT_IDX]).to.have.property('name', 'George')
expect(list[ACTIVE_CLIENT_IDX]).to.have.property('color')
expect(list[PASSIVE_CLIENT_IDX]).to.have.property('name')
expect(list[PASSIVE_CLIENT_IDX]).to.have.property('color')
})
})

Expand Down Expand Up @@ -225,12 +249,21 @@ describe('Server', () => {
)
})

it('should log info message for correct name, updated should be true and error should not exist', async () => {
it('should log info message for valid color, updated should be true, error should not exist, and a users-list event should be sent', async () => {
// arrange
await new Promise(resolve => passiveClient.on('connect', resolve))
const getUsersList = (): Promise<ExportedUser[]> =>
new Promise(resolve =>
passiveClient.on(UsersListEvent.eventName, resolve)
)

const args = { color: '#123BCA' }

// act
const value = await updateColorUser(args)
const [value, list]: [
UpdateUserColorAckArgs,
ExportedUser[]
] = await Promise.all([updateColorUser(args), getUsersList()])

// assert
expect(value).to.not.be.undefined
Expand All @@ -239,6 +272,11 @@ describe('Server', () => {
mockLogger
.getInfoLogs()
.should.include.something.that.equals(`User color updated`)
expect(list).to.have.length(2)
expect(list[ACTIVE_CLIENT_IDX]).to.have.property('name')
expect(list[ACTIVE_CLIENT_IDX]).to.have.property('color', '#123BCA')
expect(list[PASSIVE_CLIENT_IDX]).to.have.property('name')
expect(list[PASSIVE_CLIENT_IDX]).to.have.property('color')
})
})

Expand Down
24 changes: 17 additions & 7 deletions src/socket.io/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
UpdateUserNameEvent,
UpdateUserColorEvent,
} from '../domain/events/toserver'
import { User } from '../domain'
import { UsersListEvent } from '../domain/events/toclient'
import { ExportedUser, User } from '../domain'

class Socket {
private users: Map<SocketIOClient.Socket['id'], User> = new Map()
Expand Down Expand Up @@ -47,9 +48,8 @@ class Socket {
)
socketUser.name = data.name

// TODO: emit list-room-guests to all the rooms where user is logged
// TODO: alternative: send mutation : room-guest-name-updated
// this.emitLoggedUsersToRoom(socket, room)
// TODO: alternative: send mutation : user-name-updated
this.emitUsersListToAll()

this.log.info('User name updated')
ack({ updated: true })
Expand Down Expand Up @@ -85,9 +85,8 @@ class Socket {
)
socketUser.color = data.color

// TODO: emit list-room-guests to all the rooms where user is logged
// TODO: alternative: send mutation : room-guest-name-updated
// this.emitLoggedUsersToRoom(socket, room)
// TODO: alternative: send mutation : user-color-updated
this.emitUsersListToAll()

this.log.info('User color updated')
ack({ updated: true })
Expand Down Expand Up @@ -158,6 +157,17 @@ class Socket {
// )
// }

private emitUsersListToAll() {
const usersListEvent = new UsersListEvent(this.exportedUsers)
this.io
.of('/occupapp-beta')
.emit(UsersListEvent.eventName, usersListEvent.exportedUsers)
}

private get exportedUsers(): ExportedUser[] {
return [...this.users.values()].map(user => user.export())
}

private toException = (error: Error): Exception => {
return {
message: error.message,
Expand Down

0 comments on commit e36e426

Please sign in to comment.