Create test for complete game

create notifications for reply the players
implement notifications on GameEventPlayerNotificationListener
add priority to the eventbus.subscribe()
improve JWT creation
update libs koin + ktor
remove output of GameCommandStream
improve logs
create a function disableShuffleDeck to disable the shuffle of the deck (for tests)
This commit is contained in:
2025-03-08 01:07:45 +01:00
parent 99f0760d3c
commit 51d857513c
55 changed files with 659 additions and 235 deletions

View File

@@ -0,0 +1,133 @@
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
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.eventListener.GameEventPlayerNotificationListener
import eventDemo.app.eventListener.GameEventReactionListener
import eventDemo.app.notification.PlayerAsJoinTheGameNotification
import eventDemo.app.notification.PlayerAsPlayACardNotification
import eventDemo.app.notification.PlayerWasReadyNotification
import eventDemo.app.notification.TheGameWasStartedNotification
import eventDemo.app.notification.WelcomeToTheGameNotification
import eventDemo.configuration.appKoinModule
import eventDemo.send
import eventDemo.shared.toNotification
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.collections.shouldHaveSize
import io.kotest.matchers.equals.shouldBeEqual
import io.ktor.websocket.Frame
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.koin.dsl.koinApplication
import kotlin.test.assertIs
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
@DelicateCoroutinesApi
class GameStateTest :
FunSpec({
test("Simulation of a game") {
disableShuffleDeck()
val id = GameId()
val player1 = Player(name = "Nikola")
val player2 = Player(name = "Einstein")
val channelIn1 = Channel<Frame>(Channel.BUFFERED)
val channelIn2 = Channel<Frame>(Channel.BUFFERED)
val channelOut1 = Channel<Frame>(Channel.BUFFERED)
val channelOut2 = Channel<Frame>(Channel.BUFFERED)
koinApplication { modules(appKoinModule) }.koin.apply {
val commandHandler by inject<GameCommandHandler>()
val playerNotificationListener by inject<GameEventPlayerNotificationListener>()
val eventStream by inject<GameEventStream>()
GameEventReactionListener(get(), get()).init()
playerNotificationListener.startListening(channelOut1, player1)
playerNotificationListener.startListening(channelOut2, player2)
GlobalScope.launch(Dispatchers.IO) {
commandHandler.handle(player1, channelIn1, channelOut1)
}
GlobalScope.launch(Dispatchers.IO) {
commandHandler.handle(player2, channelIn2, channelOut2)
}
launch(Dispatchers.IO) {
channelIn1.send(IWantToJoinTheGameCommand(IWantToJoinTheGameCommand.Payload(id, player1)))
}
launch(Dispatchers.IO) {
delay(200)
channelIn2.send(IWantToJoinTheGameCommand(IWantToJoinTheGameCommand.Payload(id, player2)))
}
channelOut1.receive().toNotification().let {
assertIs<WelcomeToTheGameNotification>(it).players shouldBeEqual setOf(player1)
}
channelOut2.receive().toNotification().let {
assertIs<WelcomeToTheGameNotification>(it).players shouldBeEqual setOf(player1, player2)
}
channelOut1.receive().toNotification().let {
assertIs<PlayerAsJoinTheGameNotification>(it).player shouldBeEqual player2
}
launch(Dispatchers.IO) {
channelIn1.send(IamReadyToPlayCommand(IamReadyToPlayCommand.Payload(id, player1)))
}
launch(Dispatchers.IO) {
channelIn2.send(IamReadyToPlayCommand(IamReadyToPlayCommand.Payload(id, player2)))
}
channelOut1.receive().toNotification().let {
assertIs<PlayerWasReadyNotification>(it).player shouldBeEqual player2
}
channelOut2.receive().toNotification().let {
assertIs<PlayerWasReadyNotification>(it).player shouldBeEqual player1
}
val player1Hand =
channelOut1.receive().toNotification().let {
assertIs<TheGameWasStartedNotification>(it).hand shouldHaveSize 7
}
val player2Hand =
channelOut2.receive().toNotification().let {
assertIs<TheGameWasStartedNotification>(it).hand shouldHaveSize 7
}
launch {
channelIn1.send(IWantToPlayCardCommand(IWantToPlayCardCommand.Payload(id, player1, player1Hand.first())))
}
channelOut2.receive().toNotification().let {
assertIs<PlayerAsPlayACardNotification>(it).player shouldBeEqual player1
assertIs<PlayerAsPlayACardNotification>(it).card shouldBeEqual player1Hand.first()
}
launch {
channelIn2.send(IWantToPlayCardCommand(IWantToPlayCardCommand.Payload(id, player2, player2Hand.first())))
}
channelOut1.receive().toNotification().let {
assertIs<PlayerAsPlayACardNotification>(it).player shouldBeEqual player2
assertIs<PlayerAsPlayACardNotification>(it).card shouldBeEqual player2Hand.first()
}
val state = id.buildStateFromEventStream(eventStream)
state.gameId shouldBeEqual id
assertTrue(state.isStarted)
state.players shouldBeEqual setOf(player1, player2)
state.readyPlayers shouldBeEqual setOf(player1, player2)
state.direction shouldBeEqual GameState.Direction.CLOCKWISE
assertNotNull(state.lastCard) shouldBeEqual GameState.LastCard(player2Hand.first(), player2)
}
}
})