Create GameStateRepository
Use GameState.apply() to build Projection Create GameEventHandler Add PlayerWinEvent
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
package eventDemo.app.event.projection
|
||||
|
||||
import eventDemo.app.entity.Card
|
||||
import eventDemo.app.entity.GameId
|
||||
import eventDemo.app.entity.Player
|
||||
import eventDemo.app.event.event.CardIsPlayedEvent
|
||||
import eventDemo.app.event.event.GameStartedEvent
|
||||
import eventDemo.app.event.event.NewPlayerEvent
|
||||
import eventDemo.app.event.event.PlayerReadyEvent
|
||||
import eventDemo.app.event.event.disableShuffleDeck
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.equals.shouldBeEqual
|
||||
import kotlin.test.assertIs
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
class GameStateBuilderTest :
|
||||
FunSpec({
|
||||
test("apply") {
|
||||
disableShuffleDeck()
|
||||
val gameId = GameId()
|
||||
val player1 = Player(name = "Nikola")
|
||||
val player2 = Player(name = "Einstein")
|
||||
|
||||
GameState(gameId)
|
||||
.run {
|
||||
val event = NewPlayerEvent(gameId, player1)
|
||||
apply(event).also { state ->
|
||||
state.gameId shouldBeEqual gameId
|
||||
state.isReady shouldBeEqual false
|
||||
state.isStarted shouldBeEqual false
|
||||
}
|
||||
}.run {
|
||||
val event = NewPlayerEvent(gameId, player2)
|
||||
apply(event).also { state ->
|
||||
state.gameId shouldBeEqual gameId
|
||||
state.players shouldBeEqual setOf(player1, player2)
|
||||
}
|
||||
}.run {
|
||||
val event = PlayerReadyEvent(gameId, player1)
|
||||
apply(event).also { state ->
|
||||
state.gameId shouldBeEqual gameId
|
||||
state.readyPlayers shouldBeEqual setOf(player1)
|
||||
}
|
||||
}.run {
|
||||
val event = PlayerReadyEvent(gameId, player2)
|
||||
apply(event).also { state ->
|
||||
state.gameId shouldBeEqual gameId
|
||||
state.readyPlayers shouldBeEqual setOf(player1, player2)
|
||||
state.isReady shouldBeEqual true
|
||||
state.isStarted shouldBeEqual false
|
||||
}
|
||||
}.run {
|
||||
val event =
|
||||
GameStartedEvent.new(
|
||||
gameId,
|
||||
setOf(player1, player2),
|
||||
shuffleIsDisabled = true,
|
||||
)
|
||||
apply(event).also { state ->
|
||||
state.gameId shouldBeEqual gameId
|
||||
state.isStarted shouldBeEqual true
|
||||
assertIs<Card.NumericCard>(state.deck.stack.first()).let {
|
||||
it.number shouldBeEqual 6
|
||||
it.color shouldBeEqual Card.Color.Red
|
||||
}
|
||||
}
|
||||
}.run {
|
||||
val playedCard = playableCards(player1)[0]
|
||||
val event = CardIsPlayedEvent(gameId, playedCard, player1)
|
||||
apply(event).also { state ->
|
||||
state.gameId shouldBeEqual gameId
|
||||
assertNotNull(state.lastCard).card shouldBeEqual playedCard
|
||||
assertIs<Card.NumericCard>(playedCard).let {
|
||||
it.number shouldBeEqual 0
|
||||
it.color shouldBeEqual Card.Color.Red
|
||||
}
|
||||
}
|
||||
}.run {
|
||||
val playedCard = playableCards(player2)[0]
|
||||
val event = CardIsPlayedEvent(gameId, playedCard, player2)
|
||||
apply(event).also { state ->
|
||||
state.gameId shouldBeEqual gameId
|
||||
assertNotNull(state.lastCard).card shouldBeEqual playedCard
|
||||
assertIs<Card.NumericCard>(playedCard).let {
|
||||
it.number shouldBeEqual 7
|
||||
it.color shouldBeEqual Card.Color.Red
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -1,11 +1,15 @@
|
||||
package eventDemo.app.query
|
||||
|
||||
import eventDemo.app.GameState
|
||||
import eventDemo.app.entity.Card
|
||||
import eventDemo.app.entity.GameId
|
||||
import eventDemo.app.entity.Player
|
||||
import eventDemo.app.event.GameEventStream
|
||||
import eventDemo.app.event.GameEventHandler
|
||||
import eventDemo.app.event.event.CardIsPlayedEvent
|
||||
import eventDemo.app.event.event.GameStartedEvent
|
||||
import eventDemo.app.event.event.NewPlayerEvent
|
||||
import eventDemo.app.event.event.PlayerReadyEvent
|
||||
import eventDemo.app.event.projection.GameState
|
||||
import eventDemo.app.event.projection.GameStateRepository
|
||||
import eventDemo.configuration.configure
|
||||
import eventDemo.configuration.makeJwt
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
@@ -20,9 +24,13 @@ 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.delay
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.koin.core.context.stopKoin
|
||||
import org.koin.ktor.ext.inject
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertIs
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
class GameStateRouteTest :
|
||||
FunSpec({
|
||||
@@ -51,30 +59,56 @@ class GameStateRouteTest :
|
||||
|
||||
test("/game/{id}/card/last") {
|
||||
testApplication {
|
||||
val id = GameId()
|
||||
val card: Card = Card.NumericCard(1, Card.Color.Blue)
|
||||
val player = Player(name = "Nikola")
|
||||
val gameId = GameId()
|
||||
val player1 = Player(name = "Nikola")
|
||||
val player2 = Player(name = "Einstein")
|
||||
var lastPlayedCard: Card? = null
|
||||
|
||||
application {
|
||||
stopKoin()
|
||||
configure()
|
||||
|
||||
val eventStream by inject<GameEventStream>()
|
||||
eventStream.publish(
|
||||
CardIsPlayedEvent(id, Card.NumericCard(2, Card.Color.Yellow), player),
|
||||
CardIsPlayedEvent(id, card, player),
|
||||
// Other game
|
||||
CardIsPlayedEvent(GameId(), Card.NumericCard(2, Card.Color.Yellow), player),
|
||||
)
|
||||
val eventHandler by inject<GameEventHandler>()
|
||||
val stateRepo by inject<GameStateRepository>()
|
||||
runBlocking {
|
||||
eventHandler.handle(
|
||||
NewPlayerEvent(gameId, player1),
|
||||
NewPlayerEvent(gameId, player2),
|
||||
PlayerReadyEvent(gameId, player1),
|
||||
PlayerReadyEvent(gameId, player2),
|
||||
GameStartedEvent.new(
|
||||
gameId,
|
||||
setOf(player1, player2),
|
||||
shuffleIsDisabled = true,
|
||||
),
|
||||
)
|
||||
delay(100)
|
||||
lastPlayedCard = stateRepo.get(gameId).playableCards(player1).first()
|
||||
assertNotNull(lastPlayedCard)
|
||||
.let { assertIs<Card.NumericCard>(lastPlayedCard) }
|
||||
.let {
|
||||
it.number shouldBeEqual 0
|
||||
it.color shouldBeEqual Card.Color.Red
|
||||
}
|
||||
delay(100)
|
||||
eventHandler.handle(
|
||||
CardIsPlayedEvent(
|
||||
gameId,
|
||||
assertNotNull(lastPlayedCard),
|
||||
player1,
|
||||
),
|
||||
)
|
||||
delay(100)
|
||||
}
|
||||
}
|
||||
|
||||
httpClient()
|
||||
.get("/game/$id/card/last") {
|
||||
withAuth(player)
|
||||
.get("/game/$gameId/card/last") {
|
||||
withAuth(player1)
|
||||
accept(ContentType.Application.Json)
|
||||
}.apply {
|
||||
assertEquals(HttpStatusCode.OK, status, message = bodyAsText())
|
||||
assertEquals(card, call.body<Card>())
|
||||
assertEquals(assertNotNull(lastPlayedCard), call.body<Card>())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package eventDemo.app.query
|
||||
|
||||
import eventDemo.app.GameState
|
||||
import eventDemo.app.command.GameCommandHandler
|
||||
import eventDemo.app.command.command.IWantToJoinTheGameCommand
|
||||
import eventDemo.app.command.command.IWantToPlayCardCommand
|
||||
@@ -8,8 +7,9 @@ import eventDemo.app.command.command.IamReadyToPlayCommand
|
||||
import eventDemo.app.entity.GameId
|
||||
import eventDemo.app.entity.Player
|
||||
import eventDemo.app.event.GameEventStream
|
||||
import eventDemo.app.event.buildStateFromEventStream
|
||||
import eventDemo.app.event.event.disableShuffleDeck
|
||||
import eventDemo.app.event.projection.GameState
|
||||
import eventDemo.app.event.projection.buildStateFromEventStream
|
||||
import eventDemo.app.eventListener.GameEventPlayerNotificationListener
|
||||
import eventDemo.app.eventListener.GameEventReactionListener
|
||||
import eventDemo.app.notification.PlayerAsJoinTheGameNotification
|
||||
@@ -52,7 +52,7 @@ class GameStateTest :
|
||||
val commandHandler by inject<GameCommandHandler>()
|
||||
val playerNotificationListener by inject<GameEventPlayerNotificationListener>()
|
||||
val eventStream by inject<GameEventStream>()
|
||||
GameEventReactionListener(get(), get()).init()
|
||||
GameEventReactionListener(get(), get(), get()).init()
|
||||
playerNotificationListener.startListening(channelOut1, player1)
|
||||
playerNotificationListener.startListening(channelOut2, player2)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user