Create route to list all the games

This commit is contained in:
2025-03-17 22:36:08 +01:00
parent 8074881d57
commit c3155da23c
14 changed files with 304 additions and 18 deletions

View File

@@ -1,4 +1,4 @@
package eventDemo
package eventDemo.app
import eventDemo.business.entity.Card
import eventDemo.business.entity.Deck
@@ -8,5 +8,3 @@ fun Deck.allCardCount(): Int =
fun Deck.allCards(): Set<Card> =
stack + discard + playersHands.values.flatten()
// suspend fun SendChannel<Frame>.send(command: GameCommand) = send(Frame.Text(Json.encodeToString(command)))

View File

@@ -1,7 +1,7 @@
package eventDemo.app.entity
import eventDemo.allCardCount
import eventDemo.allCards
import eventDemo.app.allCardCount
import eventDemo.app.allCards
import eventDemo.business.entity.Deck
import eventDemo.business.entity.Player
import eventDemo.business.entity.initHands

View File

@@ -0,0 +1,10 @@
package eventDemo.app.query
import eventDemo.business.entity.Player
import eventDemo.configuration.ktor.makeJwt
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.header
internal fun HttpRequestBuilder.withAuth(player: Player) {
header("Authorization", "Bearer ${player.makeJwt("secret")}")
}

View File

@@ -0,0 +1,124 @@
package eventDemo.app.query
import eventDemo.business.entity.GameId
import eventDemo.business.entity.Player
import eventDemo.business.event.GameEventHandler
import eventDemo.business.event.event.GameStartedEvent
import eventDemo.business.event.event.NewPlayerEvent
import eventDemo.business.event.event.PlayerReadyEvent
import eventDemo.business.event.projection.gameList.GameList
import eventDemo.configuration.configure
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.collections.shouldContain
import io.kotest.matchers.collections.shouldHaveSize
import io.kotest.matchers.equals.shouldBeEqual
import io.ktor.client.call.body
import io.ktor.client.request.accept
import io.ktor.client.request.get
import io.ktor.client.statement.bodyAsText
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.server.testing.testApplication
import kotlinx.coroutines.runBlocking
import org.koin.core.context.stopKoin
import org.koin.ktor.ext.inject
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class GameListRouteTest :
FunSpec({
test("/games with no game started") {
testApplication {
val player1 = Player(name = "Nikola")
application {
stopKoin()
configure()
}
httpClient()
.get("/games") {
withAuth(player1)
accept(ContentType.Application.Json)
}.apply {
assertEquals(HttpStatusCode.OK, status, message = bodyAsText())
val list = call.body<List<GameList>>()
assertTrue(list.isEmpty())
}
}
}
test("/games return a game with status OPENING") {
testApplication {
val gameId = GameId()
val player1 = Player(name = "Nikola")
application {
stopKoin()
configure()
val eventHandler by inject<GameEventHandler>()
runBlocking {
eventHandler.handle(gameId) { NewPlayerEvent(gameId, player1, it) }
}
}
httpClient()
.get("/games") {
withAuth(player1)
accept(ContentType.Application.Json)
}.apply {
assertEquals(HttpStatusCode.OK, status, message = bodyAsText())
call.body<List<GameList>>().first().let {
it.status shouldBeEqual GameList.Status.OPENING
it.players shouldHaveSize 1
it.players shouldContain player1
it.winners shouldHaveSize 0
}
}
}
}
test("/games return a game with status IS_STARTED") {
testApplication {
val gameId = GameId()
val player1 = Player(name = "Nikola")
val player2 = Player(name = "Einstein")
application {
stopKoin()
configure()
val eventHandler by inject<GameEventHandler>()
runBlocking {
eventHandler.handle(gameId) { NewPlayerEvent(gameId, player1, it) }
eventHandler.handle(gameId) { NewPlayerEvent(gameId, player2, it) }
eventHandler.handle(gameId) { PlayerReadyEvent(gameId, player1, it) }
eventHandler.handle(gameId) { PlayerReadyEvent(gameId, player2, it) }
eventHandler.handle(gameId) {
GameStartedEvent.new(
gameId,
setOf(player1, player2),
it,
shuffleIsDisabled = true,
)
}
}
}
httpClient()
.get("/games") {
withAuth(player1)
accept(ContentType.Application.Json)
}.apply {
assertEquals(HttpStatusCode.OK, status, message = bodyAsText())
call.body<List<GameList>>().first().let {
it.status shouldBeEqual GameList.Status.IS_STARTED
it.players shouldHaveSize 2
it.players shouldContain player1
it.players shouldContain player2
it.winners shouldHaveSize 0
}
}
}
}
})

View File

@@ -11,15 +11,12 @@ import eventDemo.business.event.event.PlayerReadyEvent
import eventDemo.business.event.projection.gameState.GameState
import eventDemo.business.event.projection.gameState.GameStateRepository
import eventDemo.configuration.configure
import eventDemo.configuration.ktor.makeJwt
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.collections.shouldHaveSize
import io.kotest.matchers.equals.shouldBeEqual
import io.ktor.client.call.body
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.accept
import io.ktor.client.request.get
import io.ktor.client.request.header
import io.ktor.client.statement.bodyAsText
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
@@ -34,7 +31,7 @@ import kotlin.test.assertNotNull
class GameStateRouteTest :
FunSpec({
test("/game/{id}/state on empty game") {
test("/games/{id}/state on empty game") {
testApplication {
val id = GameId()
val player1 = Player(name = "Nikola")
@@ -44,7 +41,7 @@ class GameStateRouteTest :
}
httpClient()
.get("/game/$id/state") {
.get("/games/$id/state") {
withAuth(player1)
accept(ContentType.Application.Json)
}.apply {
@@ -57,7 +54,7 @@ class GameStateRouteTest :
}
}
test("/game/{id}/card/last") {
test("/games/{id}/card/last") {
testApplication {
val gameId = GameId()
val player1 = Player(name = "Nikola")
@@ -105,7 +102,7 @@ class GameStateRouteTest :
}
httpClient()
.get("/game/$gameId/card/last") {
.get("/games/$gameId/card/last") {
withAuth(player1)
accept(ContentType.Application.Json)
}.apply {
@@ -115,7 +112,3 @@ class GameStateRouteTest :
}
}
})
private fun HttpRequestBuilder.withAuth(player: Player) {
header("Authorization", "Bearer ${player.makeJwt("secret")}")
}