From f75ff2a7c8bad3574252fedf47a67e8f8c41caff Mon Sep 17 00:00:00 2001 From: Jeremy Letto Date: Sun, 17 Oct 2021 15:15:09 -0500 Subject: [PATCH] cleanup and unit tests (#4434) * put socket.updateHistory behind SessionCommand * rename /websocket files from .tsx to .ts * add unit tests to websocket commands * complete unit tests for webClient commands * secure wss Co-authored-by: Jeremy Letto --- webclient/src/setupTests.ts | 7 + .../{ProtoFiles.tsx => ProtoFiles.ts} | 0 .../websocket/{WebClient.tsx => WebClient.ts} | 8 + .../websocket/commands/RoomCommands.spec.ts | 71 +++ .../{RoomCommands.tsx => RoomCommands.ts} | 4 +- .../commands/SessionCommands.spec.ts | 479 ++++++++++++++++++ ...SessionCommands.tsx => SessionCommands.ts} | 82 +-- .../events/{RoomEvents.tsx => RoomEvents.ts} | 0 .../{SessionEvents.tsx => SessionEvents.ts} | 6 +- ...RoomPersistence.tsx => RoomPersistence.ts} | 0 ...nPersistence.tsx => SessionPersistence.ts} | 0 ...epAliveService.tsx => KeepAliveService.ts} | 0 ...ProtobufService.tsx => ProtobufService.ts} | 2 +- ...bSocketService.tsx => WebSocketService.ts} | 0 14 files changed, 611 insertions(+), 48 deletions(-) create mode 100644 webclient/src/setupTests.ts rename webclient/src/websocket/{ProtoFiles.tsx => ProtoFiles.ts} (100%) rename webclient/src/websocket/{WebClient.tsx => WebClient.ts} (91%) create mode 100644 webclient/src/websocket/commands/RoomCommands.spec.ts rename webclient/src/websocket/commands/{RoomCommands.tsx => RoomCommands.ts} (94%) create mode 100644 webclient/src/websocket/commands/SessionCommands.spec.ts rename webclient/src/websocket/commands/{SessionCommands.tsx => SessionCommands.ts} (68%) rename webclient/src/websocket/events/{RoomEvents.tsx => RoomEvents.ts} (100%) rename webclient/src/websocket/events/{SessionEvents.tsx => SessionEvents.ts} (95%) rename webclient/src/websocket/persistence/{RoomPersistence.tsx => RoomPersistence.ts} (100%) rename webclient/src/websocket/persistence/{SessionPersistence.tsx => SessionPersistence.ts} (100%) rename webclient/src/websocket/services/{KeepAliveService.tsx => KeepAliveService.ts} (100%) rename webclient/src/websocket/services/{ProtobufService.tsx => ProtobufService.ts} (99%) rename webclient/src/websocket/services/{WebSocketService.tsx => WebSocketService.ts} (100%) diff --git a/webclient/src/setupTests.ts b/webclient/src/setupTests.ts new file mode 100644 index 00000000..d434362d --- /dev/null +++ b/webclient/src/setupTests.ts @@ -0,0 +1,7 @@ +import protobuf from "protobufjs"; + +class MockProtobufRoot { + load() {} +} + +(protobuf as any).Root = MockProtobufRoot; diff --git a/webclient/src/websocket/ProtoFiles.tsx b/webclient/src/websocket/ProtoFiles.ts similarity index 100% rename from webclient/src/websocket/ProtoFiles.tsx rename to webclient/src/websocket/ProtoFiles.ts diff --git a/webclient/src/websocket/WebClient.tsx b/webclient/src/websocket/WebClient.ts similarity index 91% rename from webclient/src/websocket/WebClient.tsx rename to webclient/src/websocket/WebClient.ts index 499fbc98..46021b3f 100644 --- a/webclient/src/websocket/WebClient.tsx +++ b/webclient/src/websocket/WebClient.ts @@ -57,6 +57,14 @@ export class WebClient { this.socket.connect(this.options); } + public disconnect() { + this.socket.disconnect(); + } + + public updateStatus(status: StatusEnum, description: string) { + this.socket.updateStatus(status, description); + } + public handleStatusChange({ status, description }: ServerStatus) { SessionPersistence.updateStatus(status, description); diff --git a/webclient/src/websocket/commands/RoomCommands.spec.ts b/webclient/src/websocket/commands/RoomCommands.spec.ts new file mode 100644 index 00000000..f00a1162 --- /dev/null +++ b/webclient/src/websocket/commands/RoomCommands.spec.ts @@ -0,0 +1,71 @@ +import { RoomCommands } from './RoomCommands'; + +import { RoomPersistence } from '../persistence'; +import webClient from '../WebClient'; + +describe('RoomCommands', () => { + const roomId = 1; + let sendRoomCommandSpy; + + beforeEach(() => { + sendRoomCommandSpy = spyOn(webClient.protobuf, 'sendRoomCommand'); + + webClient.protobuf.controller.RoomCommand = { create: args => args }; + }); + + describe('roomSay', () => { + beforeEach(() => { + webClient.protobuf.controller.Command_RoomSay = { create: args => args }; + }); + + it('should call protobuf controller methods and sendCommand', () => { + const message = ' message '; + + RoomCommands.roomSay(roomId, message); + + expect(webClient.protobuf.sendRoomCommand).toHaveBeenCalled(); + expect(webClient.protobuf.sendRoomCommand).toHaveBeenCalledWith(roomId, { + '.Command_RoomSay.ext': { message: message.trim() } + }); + }); + + it('should not call sendRoomCommand if trimmed message is empty', () => { + const message = ' '; + + RoomCommands.roomSay(roomId, message); + + expect(webClient.protobuf.sendRoomCommand).not.toHaveBeenCalled(); + }); + }); + + describe('leaveRoom', () => { + beforeEach(() => { + webClient.protobuf.controller.Command_LeaveRoom = { create: () => ({}) }; + }); + + it('should call protobuf controller methods and sendCommand', () => { + RoomCommands.leaveRoom(roomId); + + expect(webClient.protobuf.sendRoomCommand).toHaveBeenCalled(); + expect(webClient.protobuf.sendRoomCommand).toHaveBeenCalledWith( + roomId, + { '.Command_LeaveRoom.ext': {} }, + jasmine.any(Function) + ); + }); + + it('should call RoomPersistence.leaveRoom if RespOk', () => { + const RespOk = 'ok'; + webClient.protobuf.controller.Response = { ResponseCode: { RespOk } }; + sendRoomCommandSpy.and.callFake((_, __, callback) => { + callback({ responseCode: RespOk }) + }); + + spyOn(RoomPersistence, 'leaveRoom'); + + RoomCommands.leaveRoom(roomId); + + expect(RoomPersistence.leaveRoom).toHaveBeenCalledWith(roomId); + }); + }); +}); \ No newline at end of file diff --git a/webclient/src/websocket/commands/RoomCommands.tsx b/webclient/src/websocket/commands/RoomCommands.ts similarity index 94% rename from webclient/src/websocket/commands/RoomCommands.tsx rename to webclient/src/websocket/commands/RoomCommands.ts index 1aa32ce5..e6173cfe 100644 --- a/webclient/src/websocket/commands/RoomCommands.tsx +++ b/webclient/src/websocket/commands/RoomCommands.ts @@ -1,11 +1,9 @@ -import * as _ from 'lodash'; - import { RoomPersistence } from '../persistence'; import webClient from "../WebClient"; export class RoomCommands { static roomSay(roomId: number, message: string) { - const trimmed = _.trim(message); + const trimmed = message.trim(); if (!trimmed) return; diff --git a/webclient/src/websocket/commands/SessionCommands.spec.ts b/webclient/src/websocket/commands/SessionCommands.spec.ts new file mode 100644 index 00000000..3a73d639 --- /dev/null +++ b/webclient/src/websocket/commands/SessionCommands.spec.ts @@ -0,0 +1,479 @@ +import { StatusEnum } from 'types'; + +import { SessionCommands } from './SessionCommands'; + +import { RoomPersistence, SessionPersistence } from '../persistence'; +import webClient from '../WebClient'; + +describe('SessionCommands', () => { + const roomId = 1; + let sendModeratorCommandSpy; + let sendSessionCommandSpy; + + beforeEach(() => { + spyOn(SessionCommands, 'updateStatus').and.callThrough(); + spyOn(webClient, 'updateStatus'); + spyOn(console, 'error'); + + sendModeratorCommandSpy = spyOn(webClient.protobuf, 'sendModeratorCommand'); + sendSessionCommandSpy = spyOn(webClient.protobuf, 'sendSessionCommand'); + webClient.protobuf.controller.ModeratorCommand = { create: args => args }; + webClient.protobuf.controller.SessionCommand = { create: args => args }; + }); + + describe('connect', () => { + it('should call SessionCommands.updateStatus and webClient.connect', () => { + spyOn(webClient, 'connect'); + const options = { + host: 'host', + port: 'port', + user: 'user', + pass: 'pass', + }; + + SessionCommands.connect(options); + + expect(SessionCommands.updateStatus).toHaveBeenCalled(); + expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.CONNECTING, 'Connecting...'); + + expect(webClient.connect).toHaveBeenCalled(); + expect(webClient.connect).toHaveBeenCalledWith(options); + }); + }); + + describe('disconnect', () => { + it('should call SessionCommands.updateStatus and webClient.disconnect', () => { + spyOn(webClient, 'disconnect'); + + SessionCommands.disconnect(); + + expect(SessionCommands.updateStatus).toHaveBeenCalled(); + expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTING, 'Disconnecting...'); + + expect(webClient.disconnect).toHaveBeenCalled(); + }); + }); + + describe('login', () => { + beforeEach(() => { + webClient.protobuf.controller.Command_Login = { create: args => args }; + webClient.options.user = 'user'; + webClient.options.pass = 'pass'; + }); + + it('should call protobuf controller methods and sendCommand', () => { + SessionCommands.login(); + + expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalled(); + expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalledWith({ + '.Command_Login.ext': { + ...webClient.clientConfig, + userName: webClient.options.user, + password: webClient.options.pass, + clientid: jasmine.any(String) + } + }, jasmine.any(Function)); + }); + + describe('response', () => { + const RespOk = 'RespOk'; + const respKey = '.Response_Login.ext'; + let response; + + beforeEach(() => { + response = { + responseCode: RespOk, + [respKey]: { + buddyList: [], + ignoreList: [], + userInfo: {} + } + }; + + webClient.protobuf.controller.Response = { ResponseCode: { RespOk } }; + + sendSessionCommandSpy.and.callFake((_, callback) => callback(response)); + }); + + it('RespOk should update user/state and list users/games', () => { + spyOn(SessionPersistence, 'updateBuddyList'); + spyOn(SessionPersistence, 'updateIgnoreList'); + spyOn(SessionPersistence, 'updateUser'); + spyOn(SessionCommands, 'listUsers'); + spyOn(SessionCommands, 'listRooms'); + + SessionCommands.login(); + + expect(SessionPersistence.updateBuddyList).toHaveBeenCalledWith(response[respKey].buddyList); + expect(SessionPersistence.updateIgnoreList).toHaveBeenCalledWith(response[respKey].ignoreList); + expect(SessionPersistence.updateUser).toHaveBeenCalledWith(response[respKey].userInfo); + + expect(SessionCommands.listUsers).toHaveBeenCalled(); + expect(SessionCommands.listRooms).toHaveBeenCalled(); + expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.LOGGEDIN, 'Logged in.'); + }); + + it('RespClientUpdateRequired should update status', () => { + const RespClientUpdateRequired = 'RespClientUpdateRequired'; + webClient.protobuf.controller.Response.ResponseCode.RespClientUpdateRequired = RespClientUpdateRequired; + response.responseCode = RespClientUpdateRequired; + + SessionCommands.login(); + + expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: missing features'); + }); + + it('RespWrongPassword should update status', () => { + const RespWrongPassword = 'RespWrongPassword'; + webClient.protobuf.controller.Response.ResponseCode.RespWrongPassword = RespWrongPassword; + response.responseCode = RespWrongPassword; + + SessionCommands.login(); + + expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: incorrect username or password'); + }); + + it('RespUsernameInvalid should update status', () => { + const RespUsernameInvalid = 'RespUsernameInvalid'; + webClient.protobuf.controller.Response.ResponseCode.RespUsernameInvalid = RespUsernameInvalid; + response.responseCode = RespUsernameInvalid; + + SessionCommands.login(); + + expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: incorrect username or password'); + }); + + it('RespWouldOverwriteOldSession should update status', () => { + const RespWouldOverwriteOldSession = 'RespWouldOverwriteOldSession'; + webClient.protobuf.controller.Response.ResponseCode.RespWouldOverwriteOldSession = RespWouldOverwriteOldSession; + response.responseCode = RespWouldOverwriteOldSession; + + SessionCommands.login(); + + expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: duplicated user session'); + }); + + it('RespUserIsBanned should update status', () => { + const RespUserIsBanned = 'RespUserIsBanned'; + webClient.protobuf.controller.Response.ResponseCode.RespUserIsBanned = RespUserIsBanned; + response.responseCode = RespUserIsBanned; + + SessionCommands.login(); + + expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: banned user'); + }); + + it('RespRegistrationRequired should update status', () => { + const RespRegistrationRequired = 'RespRegistrationRequired'; + webClient.protobuf.controller.Response.ResponseCode.RespRegistrationRequired = RespRegistrationRequired; + response.responseCode = RespRegistrationRequired; + + SessionCommands.login(); + + expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: registration required'); + }); + + it('RespClientIdRequired should update status', () => { + const RespClientIdRequired = 'RespClientIdRequired'; + webClient.protobuf.controller.Response.ResponseCode.RespClientIdRequired = RespClientIdRequired; + response.responseCode = RespClientIdRequired; + + SessionCommands.login(); + + expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: missing client ID'); + }); + + it('RespContextError should update status', () => { + const RespContextError = 'RespContextError'; + webClient.protobuf.controller.Response.ResponseCode.RespContextError = RespContextError; + response.responseCode = RespContextError; + + SessionCommands.login(); + + expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: server error'); + }); + + it('RespAccountNotActivated should update status', () => { + const RespAccountNotActivated = 'RespAccountNotActivated'; + webClient.protobuf.controller.Response.ResponseCode.RespAccountNotActivated = RespAccountNotActivated; + response.responseCode = RespAccountNotActivated; + + SessionCommands.login(); + + expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: account not activated'); + }); + + it('all other responseCodes should update status', () => { + const UnknownCode = 'UnknownCode'; + webClient.protobuf.controller.Response.ResponseCode.UnknownCode = UnknownCode; + response.responseCode = UnknownCode; + + SessionCommands.login(); + + expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, `Login failed: unknown error: ${response.responseCode}`); + }); + }); + }); + + describe('listUsers', () => { + beforeEach(() => { + webClient.protobuf.controller.Command_ListUsers = { create: () => ({}) }; + }); + + it('should call protobuf controller methods and sendCommand', () => { + SessionCommands.listUsers(); + + expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalled(); + expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalledWith({ + '.Command_ListUsers.ext': {} + }, jasmine.any(Function)); + }); + + it('should call SessionPersistence.updateUsers if RespOk', () => { + const RespOk = 'ok'; + const respKey = '.Response_ListUsers.ext'; + const response = { + responseCode: RespOk, + [respKey]: { userList: [] } + }; + + webClient.protobuf.controller.Response = { ResponseCode: { RespOk } }; + sendSessionCommandSpy.and.callFake((_, callback) => callback(response)); + spyOn(SessionPersistence, 'updateUsers'); + + SessionCommands.listUsers(); + + expect(SessionPersistence.updateUsers).toHaveBeenCalledWith(response[respKey].userList); + }); + }); + + describe('listRooms', () => { + beforeEach(() => { + webClient.protobuf.controller.Command_ListRooms = { create: () => ({}) }; + }); + + it('should call protobuf controller methods and sendCommand', () => { + SessionCommands.listRooms(); + + expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalled(); + expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalledWith({ + '.Command_ListRooms.ext': {} + }); + }); + }); + + describe('joinRoom', () => { + beforeEach(() => { + webClient.protobuf.controller.Command_JoinRoom = { create: args => args }; + }); + + it('should call protobuf controller methods and sendCommand', () => { + SessionCommands.joinRoom(roomId); + + expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalled(); + expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalledWith({ + '.Command_JoinRoom.ext': { roomId } + }, jasmine.any(Function)); + }); + + describe('response', () => { + const RespOk = 'RespOk'; + const respKey = '.Response_JoinRoom.ext'; + let response; + + beforeEach(() => { + response = { + responseCode: RespOk, + [respKey]: { roomInfo: {} } + }; + + webClient.protobuf.controller.Response = { ResponseCode: { RespOk } }; + + sendSessionCommandSpy.and.callFake((_, callback) => callback(response)); + }); + + it('RespOk should call RoomPersistence.joinRoom', () => { + spyOn(RoomPersistence, 'joinRoom'); + + SessionCommands.joinRoom(roomId); + + expect(RoomPersistence.joinRoom).toHaveBeenCalledWith(response[respKey].roomInfo); + }); + + it('RespNameNotFound should console error', () => { + const RespNameNotFound = 'RespNameNotFound'; + webClient.protobuf.controller.Response.ResponseCode.RespNameNotFound = RespNameNotFound; + response.responseCode = RespNameNotFound; + + SessionCommands.joinRoom(roomId); + + expect(console.error).toHaveBeenCalledWith(RespNameNotFound, 'Failed to join the room: it doesn\'t exist on the server.'); + }); + + it('RespContextError should console error', () => { + const RespContextError = 'RespContextError'; + webClient.protobuf.controller.Response.ResponseCode.RespContextError = RespContextError; + response.responseCode = RespContextError; + + SessionCommands.joinRoom(roomId); + + expect(console.error).toHaveBeenCalledWith(RespContextError, 'The server thinks you are in the room but Cockatrice is unable to display it. Try restarting Cockatrice.'); + }); + + it('RespUserLevelTooLow should console error', () => { + const RespUserLevelTooLow = 'RespUserLevelTooLow'; + webClient.protobuf.controller.Response.ResponseCode.RespUserLevelTooLow = RespUserLevelTooLow; + response.responseCode = RespUserLevelTooLow; + + SessionCommands.joinRoom(roomId); + + expect(console.error).toHaveBeenCalledWith(RespUserLevelTooLow, 'You do not have the required permission to join this room.'); + }); + + it('all other responseCodes should update status', () => { + const UnknownCode = 'UnknownCode'; + webClient.protobuf.controller.Response.ResponseCode.UnknownCode = UnknownCode; + response.responseCode = UnknownCode; + + SessionCommands.joinRoom(roomId); + + expect(console.error).toHaveBeenCalledWith(UnknownCode, 'Failed to join the room due to an unknown error.'); + }); + }); + }); + + describe('addToBuddyList', () => { + it('should call SessionCommands.addToList', () => { + spyOn(SessionCommands, 'addToList'); + const userName = 'userName'; + + SessionCommands.addToBuddyList(userName); + + expect(SessionCommands.addToList).toHaveBeenCalledWith('buddy', userName); + }); + }); + + describe('removeFromBuddyList', () => { + it('should call SessionCommands.removeFromList', () => { + spyOn(SessionCommands, 'removeFromList'); + const userName = 'userName'; + + SessionCommands.removeFromBuddyList(userName); + + expect(SessionCommands.removeFromList).toHaveBeenCalledWith('buddy', userName); + }); + }); + + describe('addToIgnoreList', () => { + it('should call SessionCommands.addToList', () => { + spyOn(SessionCommands, 'addToList'); + const userName = 'userName'; + + SessionCommands.addToIgnoreList(userName); + + expect(SessionCommands.addToList).toHaveBeenCalledWith('ignore', userName); + }); + }); + + describe('removeFromIgnoreList', () => { + it('should call SessionCommands.removeFromList', () => { + spyOn(SessionCommands, 'removeFromList'); + const userName = 'userName'; + + SessionCommands.removeFromIgnoreList(userName); + + expect(SessionCommands.removeFromList).toHaveBeenCalledWith('ignore', userName); + }); + }); + + describe('addToList', () => { + beforeEach(() => { + webClient.protobuf.controller.Command_AddToList = { create: args => args }; + }); + + it('should call protobuf controller methods and sendCommand', () => { + const addToList = { list: 'list', userName: 'userName'}; + SessionCommands.addToList(addToList.list, addToList.userName); + + expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalled(); + expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalledWith({ + '.Command_AddToList.ext': addToList + }, jasmine.any(Function)); + }); + }); + + describe('removeFromList', () => { + beforeEach(() => { + webClient.protobuf.controller.Command_RemoveFromList = { create: args => args }; + }); + + it('should call protobuf controller methods and sendCommand', () => { + const removeFromList = { list: 'list', userName: 'userName'}; + SessionCommands.removeFromList(removeFromList.list, removeFromList.userName); + + expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalled(); + expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalledWith({ + '.Command_RemoveFromList.ext': removeFromList + }, jasmine.any(Function)); + }); + }); + + describe('viewLogHistory', () => { + const filters = {}; + + beforeEach(() => { + webClient.protobuf.controller.Command_ViewLogHistory = { create: args => args }; + }); + + it('should call protobuf controller methods and sendCommand', () => { + SessionCommands.viewLogHistory(filters); + + expect(webClient.protobuf.sendModeratorCommand).toHaveBeenCalled(); + expect(webClient.protobuf.sendModeratorCommand).toHaveBeenCalledWith({ + '.Command_ViewLogHistory.ext': filters + }, jasmine.any(Function)); + }); + + describe('response', () => { + const RespOk = 'RespOk'; + const respKey = '.Response_ViewLogHistory.ext'; + let response; + + beforeEach(() => { + response = { + responseCode: RespOk, + [respKey]: { logMessage: {} } + }; + + webClient.protobuf.controller.Response = { ResponseCode: { RespOk } }; + + sendModeratorCommandSpy.and.callFake((_, callback) => callback(response)); + }); + + it('RespOk should call SessionPersistence.viewLogs', () => { + spyOn(SessionPersistence, 'viewLogs'); + + SessionCommands.viewLogHistory(filters); + + expect(SessionPersistence.viewLogs).toHaveBeenCalledWith(response[respKey].logMessage); + }); + + it('all other responseCodes should console error', () => { + const UnknownCode = 'UnknownCode'; + webClient.protobuf.controller.Response.ResponseCode.UnknownCode = UnknownCode; + response.responseCode = UnknownCode; + + SessionCommands.viewLogHistory(filters); + + expect(console.error).toHaveBeenCalledWith(UnknownCode, 'Failed to retrieve log history.'); + }); + }); + }); + + describe('updateStatus', () => { + it('should call webClient.updateStatus', () => { + SessionCommands.updateStatus(StatusEnum.CONNECTING, 'description'); + expect(webClient.updateStatus).toHaveBeenCalledWith(StatusEnum.CONNECTING, 'description'); + }); + }); +}); diff --git a/webclient/src/websocket/commands/SessionCommands.tsx b/webclient/src/websocket/commands/SessionCommands.ts similarity index 68% rename from webclient/src/websocket/commands/SessionCommands.tsx rename to webclient/src/websocket/commands/SessionCommands.ts index c13135b2..e3cb111f 100644 --- a/webclient/src/websocket/commands/SessionCommands.tsx +++ b/webclient/src/websocket/commands/SessionCommands.ts @@ -1,37 +1,37 @@ -import { ServerConnectParams } from "store"; -import { StatusEnum } from "types"; +import { ServerConnectParams } from 'store'; +import { StatusEnum } from 'types'; import { RoomPersistence, SessionPersistence } from '../persistence'; -import webClient from "../WebClient"; -import { guid } from "../utils"; +import webClient from '../WebClient'; +import { guid } from '../utils'; export class SessionCommands { static connect(options: ServerConnectParams) { - webClient.socket.updateStatus(StatusEnum.CONNECTING, "Connecting..."); + SessionCommands.updateStatus(StatusEnum.CONNECTING, 'Connecting...'); webClient.connect(options); } static disconnect() { - webClient.socket.updateStatus(StatusEnum.DISCONNECTING, "Disconnecting..."); - webClient.socket.disconnect(); + SessionCommands.updateStatus(StatusEnum.DISCONNECTING, 'Disconnecting...'); + webClient.disconnect(); } static login() { const loginConfig = { ...webClient.clientConfig, - "userName" : webClient.options.user, - "password" : webClient.options.pass, - "clientid" : guid() + userName: webClient.options.user, + password: webClient.options.pass, + clientid: guid() }; const CmdLogin = webClient.protobuf.controller.Command_Login.create(loginConfig); const command = webClient.protobuf.controller.SessionCommand.create({ - ".Command_Login.ext" : CmdLogin + '.Command_Login.ext' : CmdLogin }); webClient.protobuf.sendSessionCommand(command, raw => { - const resp = raw[".Response_Login.ext"]; + const resp = raw['.Response_Login.ext']; switch(raw.responseCode) { case webClient.protobuf.controller.Response.ResponseCode.RespOk: @@ -44,44 +44,44 @@ export class SessionCommands { SessionCommands.listUsers(); SessionCommands.listRooms(); - webClient.socket.updateStatus(StatusEnum.LOGGEDIN, "Logged in."); + SessionCommands.updateStatus(StatusEnum.LOGGEDIN, 'Logged in.'); break; case webClient.protobuf.controller.Response.ResponseCode.RespClientUpdateRequired: - webClient.socket.updateStatus(StatusEnum.DISCONNECTED, "Login failed: missing features"); + SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Login failed: missing features'); break; case webClient.protobuf.controller.Response.ResponseCode.RespWrongPassword: case webClient.protobuf.controller.Response.ResponseCode.RespUsernameInvalid: - webClient.socket.updateStatus(StatusEnum.DISCONNECTED, "Login failed: incorrect username or password"); + SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Login failed: incorrect username or password'); break; case webClient.protobuf.controller.Response.ResponseCode.RespWouldOverwriteOldSession: - webClient.socket.updateStatus(StatusEnum.DISCONNECTED, "Login failed: duplicated user session"); + SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Login failed: duplicated user session'); break; case webClient.protobuf.controller.Response.ResponseCode.RespUserIsBanned: - webClient.socket.updateStatus(StatusEnum.DISCONNECTED, "Login failed: banned user"); + SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Login failed: banned user'); break; case webClient.protobuf.controller.Response.ResponseCode.RespRegistrationRequired: - webClient.socket.updateStatus(StatusEnum.DISCONNECTED, "Login failed: registration required"); + SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Login failed: registration required'); break; case webClient.protobuf.controller.Response.ResponseCode.RespClientIdRequired: - webClient.socket.updateStatus(StatusEnum.DISCONNECTED, "Login failed: missing client ID"); + SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Login failed: missing client ID'); break; case webClient.protobuf.controller.Response.ResponseCode.RespContextError: - webClient.socket.updateStatus(StatusEnum.DISCONNECTED, "Login failed: server error"); + SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Login failed: server error'); break; case webClient.protobuf.controller.Response.ResponseCode.RespAccountNotActivated: - webClient.socket.updateStatus(StatusEnum.DISCONNECTED, "Login failed: account not activated"); + SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Login failed: account not activated'); break; default: - webClient.socket.updateStatus(StatusEnum.DISCONNECTED, "Login failed: unknown error " + raw.responseCode); + SessionCommands.updateStatus(StatusEnum.DISCONNECTED, `Login failed: unknown error: ${raw.responseCode}`); } }); } @@ -90,12 +90,12 @@ export class SessionCommands { const CmdListUsers = webClient.protobuf.controller.Command_ListUsers.create(); const sc = webClient.protobuf.controller.SessionCommand.create({ - ".Command_ListUsers.ext" : CmdListUsers + '.Command_ListUsers.ext' : CmdListUsers }); webClient.protobuf.sendSessionCommand(sc, raw => { const { responseCode } = raw; - const response = raw[".Response_ListUsers.ext"]; + const response = raw['.Response_ListUsers.ext']; if (response) { switch (responseCode) { @@ -114,19 +114,17 @@ export class SessionCommands { const CmdListRooms = webClient.protobuf.controller.Command_ListRooms.create(); const sc = webClient.protobuf.controller.SessionCommand.create({ - ".Command_ListRooms.ext" : CmdListRooms + '.Command_ListRooms.ext' : CmdListRooms }); webClient.protobuf.sendSessionCommand(sc); } static joinRoom(roomId: number) { - const CmdJoinRoom = webClient.protobuf.controller.Command_JoinRoom.create({ - "roomId" : roomId - }); + const CmdJoinRoom = webClient.protobuf.controller.Command_JoinRoom.create({ roomId }); const sc = webClient.protobuf.controller.SessionCommand.create({ - ".Command_JoinRoom.ext" : CmdJoinRoom + '.Command_JoinRoom.ext' : CmdJoinRoom }); webClient.protobuf.sendSessionCommand(sc, (raw) => { @@ -136,21 +134,21 @@ export class SessionCommands { switch(responseCode) { case webClient.protobuf.controller.Response.ResponseCode.RespOk: - const { roomInfo } = raw[".Response_JoinRoom.ext"]; + const { roomInfo } = raw['.Response_JoinRoom.ext']; RoomPersistence.joinRoom(roomInfo); return; case webClient.protobuf.controller.Response.ResponseCode.RespNameNotFound: - error = "Failed to join the room: it doesn\"t exist on the server."; + error = 'Failed to join the room: it doesn\'t exist on the server.'; break; case webClient.protobuf.controller.Response.ResponseCode.RespContextError: - error = "The server thinks you are in the room but Cockatrice is unable to display it. Try restarting Cockatrice."; + error = 'The server thinks you are in the room but Cockatrice is unable to display it. Try restarting Cockatrice.'; break; case webClient.protobuf.controller.Response.ResponseCode.RespUserLevelTooLow: - error = "You do not have the required permission to join this room."; + error = 'You do not have the required permission to join this room.'; break; default: - error = "Failed to join the room due to an unknown error."; + error = 'Failed to join the room due to an unknown error.'; break; } @@ -180,7 +178,7 @@ export class SessionCommands { const CmdAddToList = webClient.protobuf.controller.Command_AddToList.create({ list, userName }); const sc = webClient.protobuf.controller.SessionCommand.create({ - ".Command_AddToList.ext" : CmdAddToList + '.Command_AddToList.ext' : CmdAddToList }); webClient.protobuf.sendSessionCommand(sc, ({ responseCode }) => { @@ -192,7 +190,7 @@ export class SessionCommands { const CmdRemoveFromList = webClient.protobuf.controller.Command_RemoveFromList.create({ list, userName }); const sc = webClient.protobuf.controller.SessionCommand.create({ - ".Command_RemoveFromList.ext" : CmdRemoveFromList + '.Command_RemoveFromList.ext' : CmdRemoveFromList }); webClient.protobuf.sendSessionCommand(sc, ({ responseCode }) => { @@ -204,7 +202,7 @@ export class SessionCommands { const CmdViewLogHistory = webClient.protobuf.controller.Command_ViewLogHistory.create(filters); const sc = webClient.protobuf.controller.ModeratorCommand.create({ - ".Command_ViewLogHistory.ext" : CmdViewLogHistory + '.Command_ViewLogHistory.ext' : CmdViewLogHistory }); webClient.protobuf.sendModeratorCommand(sc, (raw) => { @@ -214,13 +212,11 @@ export class SessionCommands { switch(responseCode) { case webClient.protobuf.controller.Response.ResponseCode.RespOk: - const { logMessage } = raw[".Response_ViewLogHistory.ext"]; - - console.log("Response_ViewLogHistory: ", logMessage) + const { logMessage } = raw['.Response_ViewLogHistory.ext']; SessionPersistence.viewLogs(logMessage) return; default: - error = "Failed to retrieve log history."; + error = 'Failed to retrieve log history.'; break; } @@ -229,4 +225,8 @@ export class SessionCommands { } }); } + + static updateStatus(status: StatusEnum, description: string) { + webClient.updateStatus(status, description); + } } diff --git a/webclient/src/websocket/events/RoomEvents.tsx b/webclient/src/websocket/events/RoomEvents.ts similarity index 100% rename from webclient/src/websocket/events/RoomEvents.tsx rename to webclient/src/websocket/events/RoomEvents.ts diff --git a/webclient/src/websocket/events/SessionEvents.tsx b/webclient/src/websocket/events/SessionEvents.ts similarity index 95% rename from webclient/src/websocket/events/SessionEvents.tsx rename to webclient/src/websocket/events/SessionEvents.ts index 8f172a34..c2002c22 100644 --- a/webclient/src/websocket/events/SessionEvents.tsx +++ b/webclient/src/websocket/events/SessionEvents.ts @@ -72,7 +72,7 @@ function connectionClosed({ reason, reasonStr }: ConnectionClosedData) { } } - webClient.socket.updateStatus(StatusEnum.DISCONNECTED, message); + SessionCommands.updateStatus(StatusEnum.DISCONNECTED, message); } function listRooms({ roomList }: ListRoomsData) { @@ -116,13 +116,13 @@ function serverIdentification(info: ServerIdentificationData) { if (protocolVersion !== webClient.protocolVersion) { SessionCommands.disconnect(); - webClient.socket.updateStatus(StatusEnum.DISCONNECTED, "Protocol version mismatch: " + protocolVersion); + SessionCommands.updateStatus(StatusEnum.DISCONNECTED, "Protocol version mismatch: " + protocolVersion); return; } webClient.resetConnectionvars(); - webClient.socket.updateStatus(StatusEnum.LOGGINGIN, "Logging in..."); SessionPersistence.updateInfo(serverName, serverVersion); + SessionCommands.updateStatus(StatusEnum.LOGGINGIN, "Logging in..."); SessionCommands.login(); } diff --git a/webclient/src/websocket/persistence/RoomPersistence.tsx b/webclient/src/websocket/persistence/RoomPersistence.ts similarity index 100% rename from webclient/src/websocket/persistence/RoomPersistence.tsx rename to webclient/src/websocket/persistence/RoomPersistence.ts diff --git a/webclient/src/websocket/persistence/SessionPersistence.tsx b/webclient/src/websocket/persistence/SessionPersistence.ts similarity index 100% rename from webclient/src/websocket/persistence/SessionPersistence.tsx rename to webclient/src/websocket/persistence/SessionPersistence.ts diff --git a/webclient/src/websocket/services/KeepAliveService.tsx b/webclient/src/websocket/services/KeepAliveService.ts similarity index 100% rename from webclient/src/websocket/services/KeepAliveService.tsx rename to webclient/src/websocket/services/KeepAliveService.ts diff --git a/webclient/src/websocket/services/ProtobufService.tsx b/webclient/src/websocket/services/ProtobufService.ts similarity index 99% rename from webclient/src/websocket/services/ProtobufService.tsx rename to webclient/src/websocket/services/ProtobufService.ts index 3b3fea30..c6eb0b3d 100644 --- a/webclient/src/websocket/services/ProtobufService.tsx +++ b/webclient/src/websocket/services/ProtobufService.ts @@ -121,7 +121,7 @@ export class ProtobufService { private loadProtobufFiles() { const files = ProtoFiles.map(file => `${ProtobufService.PB_FILE_DIR}/${file}`); - + this.controller = new protobuf.Root(); this.controller.load(files, { keepCase: false }, (err, root) => { if (err) { diff --git a/webclient/src/websocket/services/WebSocketService.tsx b/webclient/src/websocket/services/WebSocketService.ts similarity index 100% rename from webclient/src/websocket/services/WebSocketService.tsx rename to webclient/src/websocket/services/WebSocketService.ts