diff --git a/client/src/config/globals.js b/client/src/config/globals.js index 6a46d43..b8a95f0 100644 --- a/client/src/config/globals.js +++ b/client/src/config/globals.js @@ -39,7 +39,8 @@ export const globals = { REVEAL_PLAYER: 'revealPlayer', CHANGE_NAME: 'changeName', START_GAME: 'startGame', - PLAYER_LEFT: 'playerLeft' + PLAYER_LEFT: 'playerLeft', + NEW_SPECTATOR: 'newSpectator' }, USER_TYPES: { MODERATOR: 'moderator', diff --git a/client/src/scripts/game.js b/client/src/scripts/game.js index 97a944d..73d6a33 100644 --- a/client/src/scripts/game.js +++ b/client/src/scripts/game.js @@ -157,6 +157,10 @@ function setClientSocketHandlers (stateBucket, gameStateRenderer, socket, timerW } }); + socket.on(globals.EVENTS.NEW_SPECTATOR, (spectator) => { + stateBucket.currentGameState.spectators.push(spectator); + }); + socket.on(globals.EVENTS.PLAYER_LEFT, (player) => { removeStartGameFunctionalityIfPresent(gameStateRenderer); toast(player.name + ' has left!', 'error', false, true, 3); diff --git a/server/config/globals.js b/server/config/globals.js index c544f7b..1c16e11 100644 --- a/server/config/globals.js +++ b/server/config/globals.js @@ -38,7 +38,8 @@ const globals = { EVENTS: { PLAYER_JOINED: 'playerJoined', PLAYER_LEFT: 'playerLeft', - SYNC_GAME_STATE: 'syncGameState' + SYNC_GAME_STATE: 'syncGameState', + NEW_SPECTATOR: 'newSpectator' }, ENVIRONMENT: { LOCAL: 'local', diff --git a/server/modules/GameManager.js b/server/modules/GameManager.js index 12ff037..7e27c62 100644 --- a/server/modules/GameManager.js +++ b/server/modules/GameManager.js @@ -284,6 +284,10 @@ class GameManager { ); this.logger.trace('new spectator: ' + spectator.name); game.spectators.push(spectator); + this.namespace.in(game.accessCode).emit( + globals.EVENTS.NEW_SPECTATOR, + GameStateCurator.mapPerson(spectator) + ); return Promise.resolve(spectator.cookie); } }; diff --git a/spec/unit/server/modules/GameManager_Spec.js b/spec/unit/server/modules/GameManager_Spec.js index 28bd36e..716a14e 100644 --- a/spec/unit/server/modules/GameManager_Spec.js +++ b/spec/unit/server/modules/GameManager_Spec.js @@ -16,6 +16,7 @@ describe('GameManager', function () { gameManager = new GameManager(logger, globals.ENVIRONMENT.PRODUCTION).getInstance(); let inObj = { emit: () => {} } namespace = { in: () => { return inObj }}; + gameManager.namespace = namespace; }); beforeEach(function () { @@ -215,4 +216,56 @@ describe('GameManager', function () { expect(socket.join).toHaveBeenCalled(); }); }); + + describe('#joinGame', function () { + it('should mark the game as full when all players have been assigned', () => { + let person = new Person("1", "123", "Placeholder", USER_TYPES.KILLED_PLAYER); + let moderator = new Person("3", "789", "Jack", USER_TYPES.MODERATOR); + moderator.assigned = true; + let game = new Game( + "abc", + globals.STATUS.IN_PROGRESS, + [ person ], + [], + false, + moderator + ); + + gameManager.joinGame(game, "Jill", "x") + + + expect(game.isFull).toEqual(true); + expect(game.people[0].name).toEqual("Jill"); + expect(game.people[0].assigned).toEqual(true); + }); + + it('should create a spectator if the game is already full and broadcast it to the room', () => { + let person = new Person("1", "123", "AlreadyJoined", USER_TYPES.KILLED_PLAYER); + let moderator = new Person("3", "789", "AlreadyTheModerator", USER_TYPES.MODERATOR); + moderator.assigned = true; + person.assigned = true; + let game = new Game( + "abc", + globals.STATUS.IN_PROGRESS, + [ person ], + [], + false, + moderator + ); + game.isFull = true; + + spyOn(gameManager.namespace.in(), 'emit'); + + gameManager.joinGame(game, "Jane", "x") + + + expect(game.isFull).toEqual(true); + expect(game.people[0].name).toEqual("AlreadyJoined"); + expect(game.moderator.name).toEqual("AlreadyTheModerator"); + expect(game.spectators.length).toEqual(1); + expect(game.spectators[0].name).toEqual("Jane"); + expect(game.spectators[0].userType).toEqual(USER_TYPES.SPECTATOR); + expect(gameManager.namespace.in().emit).toHaveBeenCalledWith(globals.EVENTS.NEW_SPECTATOR, jasmine.anything()) + }); + }); });