diff options
author | Joffrey Bion <joffrey.bion@amadeus.com> | 2018-07-05 10:38:14 +0200 |
---|---|---|
committer | Joffrey BION <joffrey.bion@gmail.com> | 2018-07-14 03:06:23 +0200 |
commit | 2c28e6e21137ec6bb1ae6ca34860ad920c289426 (patch) | |
tree | 67ba2f866e2b9d5188b26b0d3f9924b110587671 /backend/src/test/kotlin | |
parent | Rework visibilities (diff) | |
download | seven-wonders-2c28e6e21137ec6bb1ae6ca34860ad920c289426.tar.gz seven-wonders-2c28e6e21137ec6bb1ae6ca34860ad920c289426.tar.bz2 seven-wonders-2c28e6e21137ec6bb1ae6ca34860ad920c289426.zip |
Kotlin migration: Spring server
Diffstat (limited to 'backend/src/test/kotlin')
27 files changed, 1439 insertions, 0 deletions
diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/SevenWondersTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/SevenWondersTest.kt new file mode 100644 index 00000000..cf6c7ce8 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/SevenWondersTest.kt @@ -0,0 +1,151 @@ +package org.luxons.sevenwonders + +import org.junit.After +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.luxons.sevenwonders.test.api.SevenWondersClient +import org.luxons.sevenwonders.test.api.SevenWondersSession +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment +import org.springframework.boot.web.server.LocalServerPort +import org.springframework.test.context.junit4.SpringRunner +import java.util.concurrent.ExecutionException +import java.util.concurrent.TimeUnit +import java.util.concurrent.TimeoutException + +@RunWith(SpringRunner::class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +class SevenWondersTest { + + @LocalServerPort + private val randomServerPort: Int = 0 + + private lateinit var client: SevenWondersClient + + private lateinit var serverUrl: String + + @Before + fun setUpClientAndUrl() { + client = SevenWondersClient() + serverUrl = "ws://localhost:$randomServerPort" + } + + private fun disconnect(vararg sessions: SevenWondersSession) { + for (session in sessions) { + session.disconnect() + } + } + + @Test + @Throws(InterruptedException::class, ExecutionException::class, TimeoutException::class) + fun chooseName() { + val session = client.connect(serverUrl) + val playerName = "Test User" + val player = session.chooseName(playerName) + assertNotNull(player) + assertEquals(playerName, player.displayName) + session.disconnect() + } + + @Throws(InterruptedException::class, TimeoutException::class, ExecutionException::class) + private fun newPlayer(name: String): SevenWondersSession { + val otherSession = client.connect(serverUrl) + otherSession.chooseName(name) + return otherSession + } + + @Test + @Throws(InterruptedException::class, ExecutionException::class, TimeoutException::class) + fun lobbySubscription_ignoredForOutsiders() { + val ownerSession = newPlayer("GameOwner") + val session1 = newPlayer("Player1") + val session2 = newPlayer("Player2") + val gameName = "Test Game" + val lobby = ownerSession.createGame(gameName) + session1.joinGame(lobby.id) + session2.joinGame(lobby.id) + + val outsiderSession = newPlayer("Outsider") + val session = outsiderSession.jackstompSession + val started = session.subscribeEmptyMsgs("/topic/lobby/" + lobby.id + "/started") + + ownerSession.startGame(lobby.id) + val nothing = started.next(1, TimeUnit.SECONDS) + assertNull(nothing) + disconnect(ownerSession, session1, session2, outsiderSession) + } + + @Test + @Throws(InterruptedException::class, ExecutionException::class, TimeoutException::class) + fun createGame_success() { + val ownerSession = newPlayer("GameOwner") + + val gameName = "Test Game" + val lobby = ownerSession.createGame(gameName) + assertNotNull(lobby) + assertEquals(gameName, lobby.name) + + disconnect(ownerSession) + } + + @Test + @Throws(InterruptedException::class, ExecutionException::class, TimeoutException::class) + fun createGame_seenByConnectedPlayers() { + val otherSession = newPlayer("OtherPlayer") + val games = otherSession.watchGames() + + var receivedLobbies = games.next() + assertNotNull(receivedLobbies) + assertEquals(0, receivedLobbies.size.toLong()) + + val ownerSession = newPlayer("GameOwner") + val gameName = "Test Game" + val createdLobby = ownerSession.createGame(gameName) + + receivedLobbies = games.next() + assertNotNull(receivedLobbies) + assertEquals(1, receivedLobbies.size.toLong()) + val receivedLobby = receivedLobbies[0] + assertEquals(createdLobby.id, receivedLobby.id) + assertEquals(createdLobby.name, receivedLobby.name) + + disconnect(ownerSession, otherSession) + } + + @Test + @Throws(Exception::class) + fun startGame_3players() { + val session1 = newPlayer("Player1") + val session2 = newPlayer("Player2") + + val lobby = session1.createGame("Test Game") + session2.joinGame(lobby.id) + + val session3 = newPlayer("Player3") + session3.joinGame(lobby.id) + + session1.startGame(lobby.id) + + val turns1 = session1.watchTurns() + val turns2 = session2.watchTurns() + val turns3 = session3.watchTurns() + session1.sayReady() + session2.sayReady() + session3.sayReady() + val turn1 = turns1.next() + val turn2 = turns2.next() + val turn3 = turns3.next() + assertNotNull(turn1) + assertNotNull(turn2) + assertNotNull(turn3) + + disconnect(session1, session2, session3) + } + + @After + fun tearDown() { + client.stop() + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/GameBrowserControllerTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/GameBrowserControllerTest.kt new file mode 100644 index 00000000..96d4bc85 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/GameBrowserControllerTest.kt @@ -0,0 +1,114 @@ +package org.luxons.sevenwonders.controllers + +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test +import org.luxons.sevenwonders.actions.CreateGameAction +import org.luxons.sevenwonders.actions.JoinGameAction +import org.luxons.sevenwonders.controllers.GameBrowserController.UserAlreadyInGameException +import org.luxons.sevenwonders.repositories.LobbyRepository +import org.luxons.sevenwonders.repositories.PlayerNotFoundException +import org.luxons.sevenwonders.repositories.PlayerRepository +import org.luxons.sevenwonders.test.TestUtils + +class GameBrowserControllerTest { + + private lateinit var playerRepository: PlayerRepository + + private lateinit var gameBrowserController: GameBrowserController + + @Before + fun setUp() { + playerRepository = PlayerRepository() + val lobbyRepository = LobbyRepository() + val template = TestUtils.createSimpMessagingTemplate() + val lobbyController = LobbyController(lobbyRepository, playerRepository, template) + gameBrowserController = GameBrowserController(lobbyController, lobbyRepository, playerRepository, template) + } + + @Test + fun listGames_initiallyEmpty() { + val principal = TestPrincipal("testuser") + val games = gameBrowserController.listGames(principal) + assertTrue(games.isEmpty()) + } + + @Test + fun createGame_success() { + val player = playerRepository.createOrUpdate("testuser", "Test User") + val principal = TestPrincipal("testuser") + + val action = CreateGameAction("Test Game") + + val createdLobby = gameBrowserController.createGame(action, principal) + + assertEquals("Test Game", createdLobby.name) + + val games = gameBrowserController.listGames(principal) + assertFalse(games.isEmpty()) + val lobby = games.iterator().next() + assertSame(lobby, createdLobby) + assertSame(player, lobby.getPlayers()[0]) + } + + @Test(expected = PlayerNotFoundException::class) + fun createGame_failsForUnknownPlayer() { + val principal = TestPrincipal("unknown") + + val action = CreateGameAction("Test Game") + gameBrowserController.createGame(action, principal) + } + + @Test(expected = UserAlreadyInGameException::class) + fun createGame_failsWhenAlreadyInGame() { + playerRepository.createOrUpdate("testuser", "Test User") + val principal = TestPrincipal("testuser") + + val createGameAction1 = CreateGameAction("Test Game 1") + + // auto-enters the game + gameBrowserController.createGame(createGameAction1, principal) + + val createGameAction2 = CreateGameAction("Test Game 2") + + // already in a game + gameBrowserController.createGame(createGameAction2, principal) + } + + @Test + fun joinGame_success() { + val owner = playerRepository.createOrUpdate("testowner", "Test User Owner") + val ownerPrincipal = TestPrincipal("testowner") + val createGameAction = CreateGameAction("Test Game") + + val createdLobby = gameBrowserController.createGame(createGameAction, ownerPrincipal) + + val joiner = playerRepository.createOrUpdate("testjoiner", "Test User Joiner") + val joinerPrincipal = TestPrincipal("testjoiner") + val joinGameAction = JoinGameAction(createdLobby.id) + + val joinedLobby = gameBrowserController.joinGame(joinGameAction, joinerPrincipal) + + assertSame(createdLobby, joinedLobby) + assertSame(owner, joinedLobby.getPlayers()[0]) + assertSame(joiner, joinedLobby.getPlayers()[1]) + } + + @Test(expected = UserAlreadyInGameException::class) + fun joinGame_failsWhenAlreadyInGame() { + playerRepository.createOrUpdate("testowner", "Test User Owner") + val ownerPrincipal = TestPrincipal("testowner") + val createGameAction = CreateGameAction("Test Game") + + val createdLobby = gameBrowserController.createGame(createGameAction, ownerPrincipal) + + playerRepository.createOrUpdate("testjoiner", "Test User Joiner") + val joinerPrincipal = TestPrincipal("testjoiner") + val joinGameAction = JoinGameAction(createdLobby.id) + + // joins the game + gameBrowserController.joinGame(joinGameAction, joinerPrincipal) + // should fail because already in a game + gameBrowserController.joinGame(joinGameAction, joinerPrincipal) + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/HomeControllerTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/HomeControllerTest.kt new file mode 100644 index 00000000..b11ef878 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/HomeControllerTest.kt @@ -0,0 +1,26 @@ +package org.luxons.sevenwonders.controllers + +import org.junit.Assert.* +import org.junit.Test +import org.luxons.sevenwonders.actions.ChooseNameAction +import org.luxons.sevenwonders.repositories.PlayerRepository + +class HomeControllerTest { + + @Test + fun chooseName() { + val playerRepository = PlayerRepository() + val homeController = HomeController(playerRepository) + + val action = ChooseNameAction("Test User") + val principal = TestPrincipal("testuser") + + val player = homeController.chooseName(action, principal) + + assertSame(player, playerRepository.find("testuser")) + assertEquals("testuser", player.username) + assertEquals("Test User", player.displayName) + assertFalse(player.isInLobby) + assertFalse(player.isInGame) + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/LobbyControllerTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/LobbyControllerTest.kt new file mode 100644 index 00000000..6269ae40 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/LobbyControllerTest.kt @@ -0,0 +1,199 @@ +package org.luxons.sevenwonders.controllers + +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test +import org.luxons.sevenwonders.actions.ReorderPlayersAction +import org.luxons.sevenwonders.actions.UpdateSettingsAction +import org.luxons.sevenwonders.game.api.CustomizableSettings +import org.luxons.sevenwonders.game.data.WonderSidePickMethod.ALL_A +import org.luxons.sevenwonders.lobby.Lobby +import org.luxons.sevenwonders.lobby.Player +import org.luxons.sevenwonders.lobby.PlayerIsNotOwnerException +import org.luxons.sevenwonders.lobby.PlayerNotInLobbyException +import org.luxons.sevenwonders.lobby.State +import org.luxons.sevenwonders.repositories.LobbyRepository +import org.luxons.sevenwonders.repositories.PlayerNotFoundException +import org.luxons.sevenwonders.repositories.PlayerRepository +import org.luxons.sevenwonders.test.TestUtils +import java.util.Arrays +import java.util.HashMap + +class LobbyControllerTest { + + private lateinit var playerRepository: PlayerRepository + + private lateinit var lobbyRepository: LobbyRepository + + private lateinit var lobbyController: LobbyController + + @Before + fun setUp() { + val template = TestUtils.createSimpMessagingTemplate() + playerRepository = PlayerRepository() + lobbyRepository = LobbyRepository() + lobbyController = LobbyController(lobbyRepository, playerRepository, template) + } + + @Test + fun init_succeeds() { + val owner = playerRepository.createOrUpdate("testuser", "Test User") + val lobby = lobbyRepository.create("Test Game", owner) + + assertTrue(lobby.getPlayers().contains(owner)) + assertSame(lobby, owner.lobby) + assertEquals(owner.username, lobby.owner) + assertTrue(owner.isInLobby) + assertFalse(owner.isInGame) + } + + @Test(expected = PlayerNotFoundException::class) + fun leave_failsWhenPlayerDoesNotExist() { + val principal = TestPrincipal("I don't exist") + lobbyController.leave(principal) + } + + @Test(expected = PlayerNotInLobbyException::class) + fun leave_failsWhenNotInLobby() { + playerRepository.createOrUpdate("testuser", "Test User") + val principal = TestPrincipal("testuser") + lobbyController.leave(principal) + } + + @Test + fun leave_succeedsWhenInALobby_asOwner() { + val player = playerRepository.createOrUpdate("testuser", "Test User") + val lobby = lobbyRepository.create("Test Game", player) + + val principal = TestPrincipal("testuser") + lobbyController.leave(principal) + + assertFalse(lobbyRepository.list().contains(lobby)) + assertFalse(player.isInLobby) + assertFalse(player.isInGame) + } + + @Test + fun leave_succeedsWhenInALobby_asPeasant() { + val player = playerRepository.createOrUpdate("testuser", "Test User") + val lobby = lobbyRepository.create("Test Game", player) + val player2 = addPlayer(lobby, "testuser2") + + val principal = TestPrincipal("testuser2") + lobbyController.leave(principal) + + assertFalse(lobby.getPlayers().contains(player2)) + assertFalse(player2.isInLobby) + assertFalse(player2.isInGame) + } + + @Test + fun reorderPlayers_succeedsForOwner() { + val player = playerRepository.createOrUpdate("testuser", "Test User") + val lobby = lobbyRepository.create("Test Game", player) + + val player2 = addPlayer(lobby, "testuser2") + val player3 = addPlayer(lobby, "testuser3") + val player4 = addPlayer(lobby, "testuser4") + + val players = Arrays.asList(player, player2, player3, player4) + assertEquals(players, lobby.getPlayers()) + + val reorderedPlayers = Arrays.asList(player3, player, player2, player4) + val playerNames = reorderedPlayers.map { it.username } + val reorderPlayersAction = ReorderPlayersAction(playerNames) + + val principal = TestPrincipal("testuser") + lobbyController.reorderPlayers(reorderPlayersAction, principal) + + assertEquals(reorderedPlayers, lobby.getPlayers()) + } + + @Test(expected = PlayerIsNotOwnerException::class) + fun reorderPlayers_failsForPeasant() { + val player = playerRepository.createOrUpdate("testuser", "Test User") + val lobby = lobbyRepository.create("Test Game", player) + + val player2 = addPlayer(lobby, "testuser2") + val player3 = addPlayer(lobby, "testuser3") + + val reorderedPlayers = Arrays.asList(player3, player, player2) + val playerNames = reorderedPlayers.map { it.username } + val reorderPlayersAction = ReorderPlayersAction(playerNames) + + val principal = TestPrincipal("testuser2") + lobbyController.reorderPlayers(reorderPlayersAction, principal) + } + + @Test + fun updateSettings_succeedsForOwner() { + val player = playerRepository.createOrUpdate("testuser", "Test User") + val lobby = lobbyRepository.create("Test Game", player) + + addPlayer(lobby, "testuser2") + addPlayer(lobby, "testuser3") + addPlayer(lobby, "testuser4") + + assertEquals(CustomizableSettings(), lobby.settings) + + val newSettings = CustomizableSettings(12L, 5, ALL_A, 5, 5, 4, 10, 2, HashMap()) + val updateSettingsAction = UpdateSettingsAction(newSettings) + + val principal = TestPrincipal("testuser") + lobbyController.updateSettings(updateSettingsAction, principal) + + assertEquals(newSettings, lobby.settings) + } + + @Test(expected = PlayerIsNotOwnerException::class) + fun updateSettings_failsForPeasant() { + val player = playerRepository.createOrUpdate("testuser", "Test User") + val lobby = lobbyRepository.create("Test Game", player) + + addPlayer(lobby, "testuser2") + addPlayer(lobby, "testuser3") + + val updateSettingsAction = UpdateSettingsAction(CustomizableSettings()) + + val principal = TestPrincipal("testuser2") + lobbyController.updateSettings(updateSettingsAction, principal) + } + + @Test + fun startGame_succeedsForOwner() { + val player = playerRepository.createOrUpdate("testuser", "Test User") + val lobby = lobbyRepository.create("Test Game", player) + + addPlayer(lobby, "testuser2") + addPlayer(lobby, "testuser3") + addPlayer(lobby, "testuser4") + + val principal = TestPrincipal("testuser") + lobbyController.startGame(principal) + + assertSame(State.PLAYING, lobby.state) + } + + @Test(expected = PlayerIsNotOwnerException::class) + fun startGame_failsForPeasant() { + val player = playerRepository.createOrUpdate("testuser", "Test User") + val lobby = lobbyRepository.create("Test Game", player) + + addPlayer(lobby, "testuser2") + addPlayer(lobby, "testuser3") + + val principal = TestPrincipal("testuser2") + lobbyController.startGame(principal) + } + + private fun addPlayer(lobby: Lobby, username: String): Player { + val player = playerRepository.createOrUpdate(username, username) + lobby.addPlayer(player) + + assertTrue(lobby.getPlayers().contains(player)) + assertSame(lobby, player.lobby) + assertTrue(player.isInLobby) + assertFalse(player.isInGame) + return player + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/TestPrincipal.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/TestPrincipal.kt new file mode 100644 index 00000000..ce3cf317 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/TestPrincipal.kt @@ -0,0 +1,10 @@ +package org.luxons.sevenwonders.controllers + +import java.security.Principal + +internal class TestPrincipal(private val name: String) : Principal { + + override fun getName(): String { + return name + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/lobby/LobbyTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/lobby/LobbyTest.kt new file mode 100644 index 00000000..3abdde3b --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/lobby/LobbyTest.kt @@ -0,0 +1,229 @@ +package org.luxons.sevenwonders.lobby + +import org.junit.Assert.* +import org.junit.Assume.assumeTrue +import org.junit.Before +import org.junit.BeforeClass +import org.junit.Rule +import org.junit.Test +import org.junit.experimental.theories.DataPoints +import org.junit.experimental.theories.Theories +import org.junit.experimental.theories.Theory +import org.junit.rules.ExpectedException +import org.junit.runner.RunWith +import org.luxons.sevenwonders.game.api.CustomizableSettings +import org.luxons.sevenwonders.game.data.GameDefinition +import org.luxons.sevenwonders.game.data.GameDefinitionLoader +import org.luxons.sevenwonders.lobby.Lobby.* +import java.util.Arrays + +@RunWith(Theories::class) +class LobbyTest { + + @JvmField + @Rule + var thrown = ExpectedException.none() + + private lateinit var gameOwner: Player + + private lateinit var lobby: Lobby + + @Before + fun setUp() { + gameOwner = Player("gameowner", "Game owner") + lobby = Lobby(0, "Test Game", gameOwner, gameDefinition) + } + + @Test + fun testId() { + val lobby = Lobby(5, "Test Game", gameOwner, gameDefinition) + assertEquals(5, lobby.id) + } + + @Test + fun testName() { + val lobby = Lobby(5, "Test Game", gameOwner, gameDefinition) + assertEquals("Test Game", lobby.name) + } + + @Test + fun testOwner() { + val lobby = Lobby(5, "Test Game", gameOwner, gameDefinition) + assertSame(gameOwner, lobby.getPlayers()[0]) + assertSame(lobby, gameOwner.lobby) + } + + @Test + fun isOwner_falseWhenNull() { + assertFalse(lobby.isOwner(null)) + } + + @Test + fun isOwner_falseWhenEmptyString() { + assertFalse(lobby.isOwner("")) + } + + @Test + fun isOwner_falseWhenGarbageString() { + assertFalse(lobby.isOwner("this is garbage")) + } + + @Test + fun isOwner_trueWhenOwnerUsername() { + assertTrue(lobby.isOwner(gameOwner.username)) + } + + @Test + fun isOwner_falseWhenOtherPlayerName() { + val player = Player("testuser", "Test User") + lobby.addPlayer(player) + assertFalse(lobby.isOwner(player.username)) + } + + @Test + fun addPlayer_success() { + val player = Player("testuser", "Test User") + lobby.addPlayer(player) + assertTrue(lobby.containsUser("testuser")) + assertSame(lobby, player.lobby) + } + + @Test(expected = PlayerNameAlreadyUsedException::class) + fun addPlayer_failsOnSameName() { + val player = Player("testuser", "Test User") + val player2 = Player("testuser2", "Test User") + lobby.addPlayer(player) + lobby.addPlayer(player2) + } + + @Test(expected = PlayerOverflowException::class) + fun addPlayer_playerOverflowWhenTooMany() { + // the owner + the max number gives an overflow + addPlayers(gameDefinition.maxPlayers) + } + + @Test(expected = GameAlreadyStartedException::class) + fun addPlayer_failWhenGameStarted() { + // total with owner is the minimum + addPlayers(gameDefinition.minPlayers - 1) + lobby.startGame() + lobby.addPlayer(Player("soonerNextTime", "The Late Guy")) + } + + private fun addPlayers(nbPlayers: Int) { + for (i in 0 until nbPlayers) { + val player = Player("testuser$i", "Test User $i") + lobby.addPlayer(player) + } + } + + @Test(expected = UnknownPlayerException::class) + fun removePlayer_failsWhenNotPresent() { + lobby.removePlayer("anyname") + } + + @Test + fun removePlayer_success() { + val player = Player("testuser", "Test User") + lobby.addPlayer(player) + assertTrue(player.isInLobby) + assertFalse(player.isInGame) + + lobby.removePlayer("testuser") + assertFalse(lobby.containsUser("testuser")) + assertFalse(player.isInLobby) + assertFalse(player.isInGame) + } + + @Test + fun reorderPlayers_success() { + val player1 = Player("testuser1", "Test User 1") + val player2 = Player("testuser2", "Test User 2") + val player3 = Player("testuser3", "Test User 3") + lobby.addPlayer(player1) + lobby.addPlayer(player2) + lobby.addPlayer(player3) + lobby.reorderPlayers(Arrays.asList("testuser3", "testuser1", "testuser2")) + assertEquals("testuser3", lobby.getPlayers()[0].username) + assertEquals("testuser1", lobby.getPlayers()[1].username) + assertEquals("testuser2", lobby.getPlayers()[2].username) + } + + @Test(expected = UnknownPlayerException::class) + fun reorderPlayers_failsOnUnknownPlayer() { + val player1 = Player("testuser1", "Test User 1") + val player2 = Player("testuser2", "Test User 2") + val player3 = Player("testuser3", "Test User 3") + lobby.addPlayer(player1) + lobby.addPlayer(player2) + lobby.addPlayer(player3) + lobby.reorderPlayers(Arrays.asList("unknown", "testuser1", "testuser2")) + } + + @Theory + fun startGame_failsBelowMinPlayers(nbPlayers: Int) { + assumeTrue(nbPlayers < gameDefinition.minPlayers) + thrown.expect(PlayerUnderflowException::class.java) + // there is already the owner + addPlayers(nbPlayers - 1) + lobby.startGame() + } + + @Theory + fun startGame_succeedsAboveMinPlayers(nbPlayers: Int) { + assumeTrue(nbPlayers >= gameDefinition.minPlayers) + assumeTrue(nbPlayers <= gameDefinition.maxPlayers) + // there is already the owner + addPlayers(nbPlayers - 1) + + assertEquals(nbPlayers, lobby.getPlayers().size) + lobby.getPlayers().forEach { + assertSame(lobby, it.lobby) + assertTrue(it.isInLobby) + assertFalse(it.isInGame) + } + + val game = lobby.startGame() + assertNotNull(game) + lobby.getPlayers().forEachIndexed { index, it -> + assertSame(index, it.index) + assertSame(lobby, it.lobby) + assertSame(game, it.game) + assertTrue(it.isInLobby) + assertTrue(it.isInGame) + } + } + + @Test + fun startGame_switchesState() { + assertTrue(lobby.state === State.LOBBY) + // there is already the owner + addPlayers(gameDefinition.minPlayers - 1) + lobby.startGame() + assertTrue(lobby.state === State.PLAYING) + } + + @Test + fun setSettings() { + val settings = CustomizableSettings() + lobby.settings = settings + assertSame(settings, lobby.settings) + } + + companion object { + + private lateinit var gameDefinition: GameDefinition + + @JvmStatic + @DataPoints + fun nbPlayers(): IntArray { + return intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + } + + @JvmStatic + @BeforeClass + fun loadDefinition() { + gameDefinition = GameDefinitionLoader().gameDefinition + } + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/repositories/LobbyRepositoryTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/repositories/LobbyRepositoryTest.kt new file mode 100644 index 00000000..a5009d2a --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/repositories/LobbyRepositoryTest.kt @@ -0,0 +1,70 @@ +package org.luxons.sevenwonders.repositories + +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test +import org.luxons.sevenwonders.lobby.Player + +class LobbyRepositoryTest { + + private lateinit var repository: LobbyRepository + + @Before + fun setUp() { + repository = LobbyRepository() + } + + @Test + fun list_initiallyEmpty() { + assertTrue(repository.list().isEmpty()) + } + + @Test + fun list_returnsAllLobbies() { + val owner = Player("owner", "The Owner") + val lobby1 = repository.create("Test Name 1", owner) + val lobby2 = repository.create("Test Name 2", owner) + assertTrue(repository.list().contains(lobby1)) + assertTrue(repository.list().contains(lobby2)) + } + + @Test + fun create_withCorrectOwner() { + val owner = Player("owner", "The Owner") + val lobby = repository.create("Test Name", owner) + assertTrue(lobby.isOwner(owner.username)) + } + + @Test(expected = LobbyNotFoundException::class) + fun find_failsOnUnknownId() { + repository.find(123) + } + + @Test + fun find_returnsTheSameObject() { + val owner = Player("owner", "The Owner") + val lobby1 = repository.create("Test Name 1", owner) + val lobby2 = repository.create("Test Name 2", owner) + assertSame(lobby1, repository.find(lobby1.id)) + assertSame(lobby2, repository.find(lobby2.id)) + } + + @Test(expected = LobbyNotFoundException::class) + fun remove_failsOnUnknownId() { + repository.remove(123) + } + + @Test + fun remove_succeeds() { + val owner = Player("owner", "The Owner") + val lobby1 = repository.create("Test Name 1", owner) + assertNotNull(repository.find(lobby1.id)) + repository.remove(lobby1.id) + try { + repository.find(lobby1.id) + fail() // the call to find() should have failed + } catch (e: LobbyNotFoundException) { + // the lobby has been properly removed + } + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/repositories/PlayerRepositoryTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/repositories/PlayerRepositoryTest.kt new file mode 100644 index 00000000..64e3d8fd --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/repositories/PlayerRepositoryTest.kt @@ -0,0 +1,67 @@ +package org.luxons.sevenwonders.repositories + +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test + +class PlayerRepositoryTest { + + private lateinit var repository: PlayerRepository + + @Before + fun setUp() { + repository = PlayerRepository() + } + + @Test + fun contains_falseIfNoUserAdded() { + assertFalse(repository.contains("anyUsername")) + } + + @Test + fun contains_trueForCreatedPlayer() { + repository.createOrUpdate("player1", "Player 1") + assertTrue(repository.contains("player1")) + } + + @Test + fun createOrUpdate_createsProperly() { + val player1 = repository.createOrUpdate("player1", "Player 1") + assertEquals("player1", player1.username) + assertEquals("Player 1", player1.displayName) + } + + @Test + fun createOrUpdate_updatesDisplayName() { + val player1 = repository.createOrUpdate("player1", "Player 1") + val player1Updated = repository.createOrUpdate("player1", "Much Better Name") + assertSame(player1, player1Updated) + assertEquals("Much Better Name", player1Updated.displayName) + } + + @Test(expected = PlayerNotFoundException::class) + fun find_failsOnUnknownUsername() { + repository.find("anyUsername") + } + + @Test + fun find_returnsTheSameObject() { + val player1 = repository.createOrUpdate("player1", "Player 1") + val player2 = repository.createOrUpdate("player2", "Player 2") + assertSame(player1, repository.find("player1")) + assertSame(player2, repository.find("player2")) + } + + @Test(expected = PlayerNotFoundException::class) + fun remove_failsOnUnknownUsername() { + repository.remove("anyUsername") + } + + @Test + fun remove_succeeds() { + repository.createOrUpdate("player1", "Player 1") + assertTrue(repository.contains("player1")) + repository.remove("player1") + assertFalse(repository.contains("player1")) + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/TestUtils.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/TestUtils.kt new file mode 100644 index 00000000..51db8d91 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/TestUtils.kt @@ -0,0 +1,21 @@ +package org.luxons.sevenwonders.test + +import org.springframework.messaging.Message +import org.springframework.messaging.MessageChannel +import org.springframework.messaging.simp.SimpMessagingTemplate + +object TestUtils { + + fun createSimpMessagingTemplate(): SimpMessagingTemplate { + val messageChannel = object : MessageChannel { + override fun send(message: Message<*>): Boolean { + return true + } + + override fun send(message: Message<*>, timeout: Long): Boolean { + return true + } + } + return SimpMessagingTemplate(messageChannel) + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiBoard.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiBoard.kt new file mode 100644 index 00000000..a3d54773 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiBoard.kt @@ -0,0 +1,64 @@ +package org.luxons.sevenwonders.test.api + +import java.util.Objects + +import org.luxons.sevenwonders.game.cards.Card +import org.luxons.sevenwonders.game.effects.SpecialAbility + +class ApiBoard { + + var wonder: ApiWonder? = null + + var playerIndex: Int = 0 + + var playedCards: List<ApiCard>? = null + + var production: ApiProduction? = null + + var publicProduction: ApiProduction? = null + + var science: ApiScience? = null + + var tradingRules: ApiTradingRules? = null + + var military: ApiMilitary? = null + + var specialAbilities: Set<SpecialAbility>? = null + + var consumedFreeCards: Map<Int, Boolean>? = null + + var copiedGuild: Card? = null + + var gold: Int = 0 + + var pointsPer3Gold: Int = 0 + + override fun equals(o: Any?): Boolean { + if (this === o) { + return true + } + if (o == null || javaClass != o.javaClass) { + return false + } + val apiBoard = o as ApiBoard? + return (playerIndex == apiBoard!!.playerIndex && gold == apiBoard.gold && pointsPer3Gold == apiBoard.pointsPer3Gold && wonder == apiBoard.wonder && playedCards == apiBoard.playedCards && production == apiBoard.production && publicProduction == apiBoard.publicProduction && science == apiBoard.science && tradingRules == apiBoard.tradingRules && military == apiBoard.military && specialAbilities == apiBoard.specialAbilities && consumedFreeCards == apiBoard.consumedFreeCards && copiedGuild == apiBoard.copiedGuild) + } + + override fun hashCode(): Int { + return Objects.hash( + wonder, + playerIndex, + playedCards, + production, + publicProduction, + science, + tradingRules, + military, + specialAbilities, + consumedFreeCards, + copiedGuild, + gold, + pointsPer3Gold + ) + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiCard.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiCard.kt new file mode 100644 index 00000000..2f473367 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiCard.kt @@ -0,0 +1,38 @@ +package org.luxons.sevenwonders.test.api + +import java.util.Objects + +import org.luxons.sevenwonders.game.cards.Color +import org.luxons.sevenwonders.game.cards.Requirements + +class ApiCard { + + var name: String? = null + + var color: Color? = null + + var requirements: Requirements? = null + + var chainParent: String? = null + + var chainChildren: List<String>? = null + + var image: String? = null + + var back: ApiCardBack? = null + + override fun equals(o: Any?): Boolean { + if (this === o) { + return true + } + if (o == null || javaClass != o.javaClass) { + return false + } + val apiCard = o as ApiCard? + return name == apiCard!!.name && color === apiCard.color && requirements == apiCard.requirements && chainParent == apiCard.chainParent && chainChildren == apiCard.chainChildren && image == apiCard.image && back == apiCard.back + } + + override fun hashCode(): Int { + return Objects.hash(name, color, requirements, chainParent, chainChildren, image, back) + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiCardBack.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiCardBack.kt new file mode 100644 index 00000000..15bfd009 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiCardBack.kt @@ -0,0 +1,6 @@ +package org.luxons.sevenwonders.test.api + +class ApiCardBack { + + var image: String? = null +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiEffect.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiEffect.kt new file mode 100644 index 00000000..afe8809f --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiEffect.kt @@ -0,0 +1,3 @@ +package org.luxons.sevenwonders.test.api + +class ApiEffect diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiHandCard.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiHandCard.kt new file mode 100644 index 00000000..003c3783 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiHandCard.kt @@ -0,0 +1,16 @@ +package org.luxons.sevenwonders.test.api + +/** + * A card with contextual information relative to the hand it is sitting in. The extra information is especially + * useful because it frees the client from a painful business logic implementation. + */ +class ApiHandCard { + + var card: ApiCard? = null + + var isChainable: Boolean = false + + var isFree: Boolean = false + + var isPlayable: Boolean = false +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiLobby.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiLobby.kt new file mode 100644 index 00000000..5bc4dad6 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiLobby.kt @@ -0,0 +1,36 @@ +package org.luxons.sevenwonders.test.api + +import java.util.Objects + +import org.luxons.sevenwonders.game.api.CustomizableSettings +import org.luxons.sevenwonders.lobby.State + +class ApiLobby { + + var id: Long = 0 + + var name: String? = null + + var owner: String? = null + + var players: List<ApiPlayer>? = null + + var settings: CustomizableSettings? = null + + var state: State? = null + + override fun equals(o: Any?): Boolean { + if (this === o) { + return true + } + if (o == null || javaClass != o.javaClass) { + return false + } + val apiLobby = o as ApiLobby? + return (id == apiLobby!!.id && name == apiLobby.name && owner == apiLobby.owner && players == apiLobby.players && settings == apiLobby.settings && state === apiLobby.state) + } + + override fun hashCode(): Int { + return Objects.hash(id, name, owner, players, settings, state) + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiMilitary.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiMilitary.kt new file mode 100644 index 00000000..23e4f34c --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiMilitary.kt @@ -0,0 +1,10 @@ +package org.luxons.sevenwonders.test.api + +class ApiMilitary { + + var nbShields = 0 + + var totalPoints = 0 + + var nbDefeatTokens = 0 +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiPlayer.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiPlayer.kt new file mode 100644 index 00000000..fc4c01fb --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiPlayer.kt @@ -0,0 +1,27 @@ +package org.luxons.sevenwonders.test.api + +import java.util.Objects + +class ApiPlayer { + + val username: String? = null + + var displayName: String? = null + + var index: Int = 0 + + override fun equals(o: Any?): Boolean { + if (this === o) { + return true + } + if (o == null || javaClass != o.javaClass) { + return false + } + val apiPlayer = o as ApiPlayer? + return index == apiPlayer!!.index && username == apiPlayer.username && displayName == apiPlayer.displayName + } + + override fun hashCode(): Int { + return Objects.hash(username, displayName, index) + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiPlayerTurnInfo.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiPlayerTurnInfo.kt new file mode 100644 index 00000000..ae22cdb6 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiPlayerTurnInfo.kt @@ -0,0 +1,37 @@ +package org.luxons.sevenwonders.test.api + +import java.util.Objects + +import org.luxons.sevenwonders.game.api.Action + +class ApiPlayerTurnInfo { + + var playerIndex: Int = 0 + + var table: ApiTable? = null + + var currentAge: Int = 0 + + var action: Action? = null + + var hand: List<ApiHandCard>? = null + + var neighbourGuildCards: List<ApiCard>? = null + + var message: String? = null + + override fun equals(o: Any?): Boolean { + if (this === o) { + return true + } + if (o == null || javaClass != o.javaClass) { + return false + } + val that = o as ApiPlayerTurnInfo? + return (playerIndex == that!!.playerIndex && currentAge == that.currentAge && table == that.table && action === that.action && hand == that.hand && neighbourGuildCards == that.neighbourGuildCards && message == that.message) + } + + override fun hashCode(): Int { + return Objects.hash(playerIndex, table, currentAge, action, hand, neighbourGuildCards, message) + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiProduction.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiProduction.kt new file mode 100644 index 00000000..2ab7c343 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiProduction.kt @@ -0,0 +1,11 @@ +package org.luxons.sevenwonders.test.api + +import org.luxons.sevenwonders.game.resources.ResourceType +import org.luxons.sevenwonders.game.resources.Resources + +class ApiProduction { + + var fixedResources: Resources? = null + + var alternativeResources: Set<Set<ResourceType>>? = null +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiScience.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiScience.kt new file mode 100644 index 00000000..5e619904 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiScience.kt @@ -0,0 +1,10 @@ +package org.luxons.sevenwonders.test.api + +import org.luxons.sevenwonders.game.boards.ScienceType + +class ApiScience { + + var quantities: Map<ScienceType, Int>? = null + + var jokers: Int = 0 +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiTable.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiTable.kt new file mode 100644 index 00000000..cffbdf2f --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiTable.kt @@ -0,0 +1,23 @@ +package org.luxons.sevenwonders.test.api + +import org.luxons.sevenwonders.game.cards.HandRotationDirection +import org.luxons.sevenwonders.game.moves.Move + +class ApiTable { + + var nbPlayers: Int = 0 + + var boards: List<ApiBoard>? = null + + var currentAge = 0 + + var handRotationDirection: HandRotationDirection? = null + + var lastPlayedMoves: List<Move>? = null + + var neighbourGuildCards: List<ApiCard>? = null + + fun increaseCurrentAge() { + this.currentAge++ + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiTradingRules.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiTradingRules.kt new file mode 100644 index 00000000..fcebe59e --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiTradingRules.kt @@ -0,0 +1,9 @@ +package org.luxons.sevenwonders.test.api + +import org.luxons.sevenwonders.game.resources.Provider +import org.luxons.sevenwonders.game.resources.ResourceType + +class ApiTradingRules { + + var costs: Map<ResourceType, Map<Provider, Int>>? = null +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiWonder.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiWonder.kt new file mode 100644 index 00000000..1efe7917 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiWonder.kt @@ -0,0 +1,16 @@ +package org.luxons.sevenwonders.test.api + +import org.luxons.sevenwonders.game.resources.ResourceType + +class ApiWonder { + + private val name: String? = null + + private val initialResource: ResourceType? = null + + private val stages: List<ApiWonderStage>? = null + + private val image: String? = null + + private val nbBbuiltStages: Int = 0 +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiWonderStage.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiWonderStage.kt new file mode 100644 index 00000000..41925a55 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/ApiWonderStage.kt @@ -0,0 +1,13 @@ +package org.luxons.sevenwonders.test.api + +import org.luxons.sevenwonders.game.cards.CardBack +import org.luxons.sevenwonders.game.cards.Requirements + +class ApiWonderStage { + + var requirements: Requirements? = null + + var cardBack: CardBack? = null + + var isBuilt: Boolean = false +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersClient.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersClient.kt new file mode 100644 index 00000000..d98e932e --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersClient.kt @@ -0,0 +1,25 @@ +package org.luxons.sevenwonders.test.api + +import java.util.concurrent.ExecutionException +import java.util.concurrent.TimeoutException + +import org.hildan.jackstomp.JackstompClient +import org.hildan.jackstomp.JackstompSession + +class SevenWondersClient @JvmOverloads constructor(private val client: JackstompClient = JackstompClient()) { + + @Throws(InterruptedException::class, ExecutionException::class, TimeoutException::class) + fun connect(serverUrl: String): SevenWondersSession { + val session = client.connect(serverUrl + WEBSOCKET_ENDPOINT) + return SevenWondersSession(session) + } + + fun stop() { + client.stop() + } + + companion object { + + private val WEBSOCKET_ENDPOINT = "/seven-wonders-websocket" + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersSession.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersSession.kt new file mode 100644 index 00000000..90b40cb0 --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersSession.kt @@ -0,0 +1,70 @@ +package org.luxons.sevenwonders.test.api + +import org.hildan.jackstomp.Channel +import org.hildan.jackstomp.JackstompSession +import org.junit.Assert.* +import org.luxons.sevenwonders.actions.ChooseNameAction +import org.luxons.sevenwonders.actions.CreateGameAction +import org.luxons.sevenwonders.actions.JoinGameAction +import org.luxons.sevenwonders.errors.ErrorDTO + +class SevenWondersSession(val jackstompSession: JackstompSession) { + + fun disconnect() { + jackstompSession.disconnect() + } + + fun watchErrors(): Channel<ErrorDTO> { + return jackstompSession.subscribe("/user/queue/errors", ErrorDTO::class.java) + } + + @Throws(InterruptedException::class) + fun chooseName(displayName: String): ApiPlayer { + val action = ChooseNameAction(displayName) + return jackstompSession.request(action, ApiPlayer::class.java, "/app/chooseName", "/user/queue/nameChoice") + } + + fun watchGames(): Channel<Array<ApiLobby>> { + return jackstompSession.subscribe("/topic/games", Array<ApiLobby>::class.java) + } + + @Throws(InterruptedException::class) + fun createGame(gameName: String): ApiLobby { + val action = CreateGameAction(gameName) + return jackstompSession.request(action, ApiLobby::class.java, "/app/lobby/create", "/user/queue/lobby/joined") + } + + @Throws(InterruptedException::class) + fun joinGame(gameId: Long): ApiLobby { + val action = JoinGameAction(gameId) + val lobby = + jackstompSession.request(action, ApiLobby::class.java, "/app/lobby/join", "/user/queue/lobby/joined") + assertNotNull(lobby) + assertEquals(gameId, lobby.id) + return lobby + } + + fun watchLobbyUpdates(gameId: Long): Channel<ApiLobby> { + return jackstompSession.subscribe("/topic/lobby/$gameId/updated", ApiLobby::class.java) + } + + fun watchLobbyStart(gameId: Long): Channel<ApiLobby> { + return jackstompSession.subscribe("/topic/lobby/$gameId/started", ApiLobby::class.java) + } + + @Throws(InterruptedException::class) + fun startGame(gameId: Long) { + val sendDestination = "/app/lobby/startGame" + val receiveDestination = "/topic/lobby/$gameId/started" + val received = jackstompSession.request(null, sendDestination, receiveDestination) + assertTrue(received) + } + + fun sayReady() { + jackstompSession.send("/app/game/sayReady", "") + } + + fun watchTurns(): Channel<ApiPlayerTurnInfo> { + return jackstompSession.subscribe("/user/queue/game/turn", ApiPlayerTurnInfo::class.java) + } +} diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/validation/DestinationAccessValidatorTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/validation/DestinationAccessValidatorTest.kt new file mode 100644 index 00000000..45e58b7f --- /dev/null +++ b/backend/src/test/kotlin/org/luxons/sevenwonders/validation/DestinationAccessValidatorTest.kt @@ -0,0 +1,138 @@ +package org.luxons.sevenwonders.validation + +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.luxons.sevenwonders.lobby.Lobby +import org.luxons.sevenwonders.lobby.Player +import org.luxons.sevenwonders.repositories.LobbyNotFoundException +import org.luxons.sevenwonders.repositories.LobbyRepository + +class DestinationAccessValidatorTest { + + private lateinit var lobbyRepository: LobbyRepository + + private lateinit var destinationAccessValidator: DestinationAccessValidator + + @Before + fun setup() { + lobbyRepository = LobbyRepository() + destinationAccessValidator = DestinationAccessValidator(lobbyRepository) + } + + private fun createLobby(gameName: String, ownerUsername: String, vararg otherPlayers: String): Lobby { + val owner = Player(ownerUsername, ownerUsername) + val lobby = lobbyRepository.create(gameName, owner) + for (playerName in otherPlayers) { + val player = Player(playerName, playerName) + lobby.addPlayer(player) + } + return lobby + } + + private fun createGame(gameName: String, ownerUsername: String, vararg otherPlayers: String) { + val lobby = createLobby(gameName, ownerUsername, *otherPlayers) + lobby.startGame() + } + + @Test + fun validate_failsOnNullUser() { + assertFalse(destinationAccessValidator.hasAccess(null, "doesNotMatter")) + } + + @Test + fun validate_successWhenNoReference() { + assertTrue(destinationAccessValidator.hasAccess("", "")) + assertTrue(destinationAccessValidator.hasAccess("", "test")) + assertTrue(destinationAccessValidator.hasAccess("testUser", "test")) + } + + @Test + fun validate_successWhenNoRefFollows() { + assertTrue(destinationAccessValidator.hasAccess("testUser", "/game/")) + assertTrue(destinationAccessValidator.hasAccess("testUser", "/lobby/")) + assertTrue(destinationAccessValidator.hasAccess("testUser", "prefix/game/")) + assertTrue(destinationAccessValidator.hasAccess("testUser", "prefix/lobby/")) + assertTrue(destinationAccessValidator.hasAccess("testUser", "/game//suffix")) + assertTrue(destinationAccessValidator.hasAccess("testUser", "/lobby//suffix")) + } + + @Test + fun validate_successWhenRefIsNotANumber() { + assertTrue(destinationAccessValidator.hasAccess("testUser", "/game/notANumber")) + assertTrue(destinationAccessValidator.hasAccess("testUser", "/lobby/notANumber")) + assertTrue(destinationAccessValidator.hasAccess("testUser", "prefix/game/notANumber")) + assertTrue(destinationAccessValidator.hasAccess("testUser", "prefix/lobby/notANumber")) + assertTrue(destinationAccessValidator.hasAccess("testUser", "/game/notANumber/suffix")) + assertTrue(destinationAccessValidator.hasAccess("testUser", "/lobby/notANumber/suffix")) + } + + @Test(expected = LobbyNotFoundException::class) + fun validate_failWhenNoLobbyExist() { + destinationAccessValidator.hasAccess("", "/lobby/0") + } + + @Test(expected = LobbyNotFoundException::class) + fun validate_failWhenNoGameExist() { + destinationAccessValidator.hasAccess("", "/game/0") + } + + @Test(expected = LobbyNotFoundException::class) + fun validate_failWhenReferencedLobbyDoesNotExist() { + createLobby("Test Game", "ownerUser1") + createLobby("Test Game 2", "ownerUser2") + destinationAccessValidator.hasAccess("doesNotMatter", "/lobby/3") + } + + @Test(expected = LobbyNotFoundException::class) + fun validate_failWhenReferencedGameDoesNotExist() { + createGame("Test Game 1", "user1", "user2", "user3") + createGame("Test Game 2", "user4", "user5", "user6") + destinationAccessValidator.hasAccess("doesNotMatter", "/game/3") + } + + @Test + fun validate_failWhenUserIsNotPartOfReferencedLobby() { + createLobby("Test Game", "ownerUser") + destinationAccessValidator.hasAccess("userNotInLobby", "/lobby/0") + } + + @Test + fun validate_failWhenUserIsNotPartOfReferencedGame() { + createGame("Test Game", "ownerUser", "otherUser1", "otherUser2") + destinationAccessValidator.hasAccess("userNotInGame", "/game/0") + } + + @Test + fun validate_successWhenUserIsOwnerOfReferencedLobby() { + createLobby("Test Game 1", "user1") + assertTrue(destinationAccessValidator.hasAccess("user1", "/lobby/0")) + createLobby("Test Game 2", "user2") + assertTrue(destinationAccessValidator.hasAccess("user2", "/lobby/1")) + } + + @Test + fun validate_successWhenUserIsMemberOfReferencedLobby() { + createLobby("Test Game 1", "user1", "user2") + assertTrue(destinationAccessValidator.hasAccess("user2", "/lobby/0")) + createLobby("Test Game 2", "user3", "user4") + assertTrue(destinationAccessValidator.hasAccess("user4", "/lobby/1")) + } + + @Test + fun validate_successWhenUserIsOwnerOfReferencedGame() { + createGame("Test Game 1", "owner1", "user2", "user3") + assertTrue(destinationAccessValidator.hasAccess("owner1", "/game/0")) + createGame("Test Game 2", "owner4", "user5", "user6") + assertTrue(destinationAccessValidator.hasAccess("owner4", "/game/1")) + } + + @Test + fun validate_successWhenUserIsMemberOfReferencedGame() { + createGame("Test Game 1", "owner1", "user2", "user3") + assertTrue(destinationAccessValidator.hasAccess("user2", "/game/0")) + createGame("Test Game 2", "owner4", "user5", "user6") + assertTrue(destinationAccessValidator.hasAccess("user6", "/game/1")) + } +} |