Add AggregateID for the PlayerNotificationEventListener and CommandHandler
This commit is contained in:
@@ -7,5 +7,5 @@ import eventDemo.libs.event.EventBus
|
|||||||
import eventDemo.libs.event.EventBusInMemory
|
import eventDemo.libs.event.EventBusInMemory
|
||||||
|
|
||||||
class GameEventBusInMemory :
|
class GameEventBusInMemory :
|
||||||
GameEventBus,
|
GameEventBus(),
|
||||||
EventBus<GameEvent, GameId> by EventBusInMemory<GameEvent, GameId>()
|
EventBus<GameEvent, GameId> by EventBusInMemory()
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
package eventDemo.adapter.interfaceLayer
|
package eventDemo.adapter.interfaceLayer
|
||||||
|
|
||||||
import eventDemo.business.command.GameCommandHandler
|
import eventDemo.business.command.GameCommandHandler
|
||||||
|
import eventDemo.business.entity.GameId
|
||||||
import eventDemo.business.entity.Player
|
import eventDemo.business.entity.Player
|
||||||
import eventDemo.business.event.eventListener.PlayerNotificationEventListener
|
import eventDemo.business.event.eventListener.PlayerNotificationEventListener
|
||||||
import eventDemo.business.notification.Notification
|
import eventDemo.business.notification.Notification
|
||||||
|
import eventDemo.configuration.ktor.BadRequestException
|
||||||
|
import eventDemo.configuration.ktor.HttpErrorBadRequest
|
||||||
import eventDemo.libs.fromFrameChannel
|
import eventDemo.libs.fromFrameChannel
|
||||||
import eventDemo.libs.toObjectChannel
|
import eventDemo.libs.toObjectChannel
|
||||||
import io.github.oshai.kotlinlogging.withLoggingContext
|
import io.github.oshai.kotlinlogging.withLoggingContext
|
||||||
|
import io.ktor.http.parameters
|
||||||
import io.ktor.server.application.ApplicationCall
|
import io.ktor.server.application.ApplicationCall
|
||||||
import io.ktor.server.auth.authenticate
|
import io.ktor.server.auth.authenticate
|
||||||
import io.ktor.server.auth.jwt.JWTPrincipal
|
import io.ktor.server.auth.jwt.JWTPrincipal
|
||||||
@@ -18,6 +22,7 @@ import kotlinx.coroutines.GlobalScope
|
|||||||
import kotlinx.coroutines.channels.SendChannel
|
import kotlinx.coroutines.channels.SendChannel
|
||||||
import kotlinx.coroutines.channels.trySendBlocking
|
import kotlinx.coroutines.channels.trySendBlocking
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
@DelicateCoroutinesApi
|
@DelicateCoroutinesApi
|
||||||
fun Route.gameWebSocket(
|
fun Route.gameWebSocket(
|
||||||
@@ -25,18 +30,27 @@ fun Route.gameWebSocket(
|
|||||||
commandHandler: GameCommandHandler,
|
commandHandler: GameCommandHandler,
|
||||||
) {
|
) {
|
||||||
authenticate {
|
authenticate {
|
||||||
webSocket("/game") {
|
webSocket("/game/{id}") {
|
||||||
val currentPlayer = call.getPlayer()
|
val currentPlayer = call.getPlayer()
|
||||||
|
val gameId =
|
||||||
|
call.parameters["id"]?.let { GameId(UUID.fromString(it)) }
|
||||||
|
?: throw BadRequestException(HttpErrorBadRequest("No ID fore the game"))
|
||||||
val outgoingFrameChannel: SendChannel<Notification> = fromFrameChannel(outgoing)
|
val outgoingFrameChannel: SendChannel<Notification> = fromFrameChannel(outgoing)
|
||||||
withLoggingContext("currentPlayer" to currentPlayer.toString()) {
|
withLoggingContext("currentPlayer" to currentPlayer.toString()) {
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
commandHandler.handle(
|
commandHandler.handle(
|
||||||
currentPlayer,
|
currentPlayer,
|
||||||
|
gameId,
|
||||||
toObjectChannel(incoming),
|
toObjectChannel(incoming),
|
||||||
outgoingFrameChannel,
|
outgoingFrameChannel,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
playerNotificationListener.startListening({ outgoingFrameChannel.trySendBlocking(it) }, currentPlayer)
|
|
||||||
|
playerNotificationListener.startListening(
|
||||||
|
{ outgoingFrameChannel.trySendBlocking(it) },
|
||||||
|
currentPlayer,
|
||||||
|
gameId,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package eventDemo.business.command
|
package eventDemo.business.command
|
||||||
|
|
||||||
import eventDemo.business.command.command.GameCommand
|
import eventDemo.business.command.command.GameCommand
|
||||||
|
import eventDemo.business.entity.GameId
|
||||||
import eventDemo.business.entity.Player
|
import eventDemo.business.entity.Player
|
||||||
import eventDemo.business.event.GameEventBus
|
import eventDemo.business.event.GameEventBus
|
||||||
import eventDemo.business.event.GameEventHandler
|
import eventDemo.business.event.GameEventHandler
|
||||||
@@ -55,15 +56,24 @@ class GameCommandHandler(
|
|||||||
*/
|
*/
|
||||||
suspend fun handle(
|
suspend fun handle(
|
||||||
player: Player,
|
player: Player,
|
||||||
|
gameId: GameId,
|
||||||
incomingCommandChannel: ReceiveChannel<GameCommand>,
|
incomingCommandChannel: ReceiveChannel<GameCommand>,
|
||||||
channelNotification: SendChannel<Notification>,
|
channelNotification: SendChannel<Notification>,
|
||||||
) {
|
) {
|
||||||
commandStreamChannel.process(incomingCommandChannel) { command ->
|
commandStreamChannel.process(incomingCommandChannel) { command ->
|
||||||
withLoggingContext("command" to command.toString()) {
|
withLoggingContext("command" to command.toString()) {
|
||||||
|
if (command.payload.aggregateId.id != gameId.id) {
|
||||||
|
logger.warn { "Handle command Refuse, the gameId of the command is not the same" }
|
||||||
|
channelNotification.sendError(command)("The gameId in the command does not match with your game")
|
||||||
|
return@process
|
||||||
|
}
|
||||||
|
|
||||||
if (command.payload.player.id != player.id) {
|
if (command.payload.player.id != player.id) {
|
||||||
logger.warn { "Handle command Refuse, the player of the command is not the same" }
|
logger.warn { "Handle command Refuse, the player of the command is not the same" }
|
||||||
channelNotification.sendError(command)("You are not the author of this command")
|
channelNotification.sendError(command)("You are not the author of this command")
|
||||||
} else {
|
return@process
|
||||||
|
}
|
||||||
|
|
||||||
logger.info { "Handle command" }
|
logger.info { "Handle command" }
|
||||||
try {
|
try {
|
||||||
val eventBuilder = runner.run(command)
|
val eventBuilder = runner.run(command)
|
||||||
@@ -80,7 +90,6 @@ class GameCommandHandler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun SendChannel<Notification>.sendSuccess(commandId: CommandId): suspend () -> Unit =
|
private fun SendChannel<Notification>.sendSuccess(commandId: CommandId): suspend () -> Unit =
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,5 +3,13 @@ package eventDemo.business.event
|
|||||||
import eventDemo.business.entity.GameId
|
import eventDemo.business.entity.GameId
|
||||||
import eventDemo.business.event.event.GameEvent
|
import eventDemo.business.event.event.GameEvent
|
||||||
import eventDemo.libs.event.EventBus
|
import eventDemo.libs.event.EventBus
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
interface GameEventBus : EventBus<GameEvent, GameId>
|
abstract class GameEventBus :
|
||||||
|
EventBus<GameEvent, GameId>,
|
||||||
|
Comparable<GameEventBus> {
|
||||||
|
private val instanceId: UUID = UUID.randomUUID()
|
||||||
|
|
||||||
|
override fun compareTo(other: GameEventBus): Int =
|
||||||
|
compareValues(instanceId, other.instanceId)
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ data class GameStartedEvent(
|
|||||||
fun new(
|
fun new(
|
||||||
id: GameId,
|
id: GameId,
|
||||||
players: Set<Player>,
|
players: Set<Player>,
|
||||||
shuffleIsDisabled: Boolean = isDisabled,
|
|
||||||
version: Int,
|
version: Int,
|
||||||
|
shuffleIsDisabled: Boolean = isDisabled,
|
||||||
): GameStartedEvent =
|
): GameStartedEvent =
|
||||||
GameStartedEvent(
|
GameStartedEvent(
|
||||||
aggregateId = id,
|
aggregateId = id,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package eventDemo.business.event.eventListener
|
package eventDemo.business.event.eventListener
|
||||||
|
|
||||||
import eventDemo.business.entity.Card
|
import eventDemo.business.entity.Card
|
||||||
|
import eventDemo.business.entity.GameId
|
||||||
import eventDemo.business.entity.Player
|
import eventDemo.business.entity.Player
|
||||||
import eventDemo.business.event.GameEventBus
|
import eventDemo.business.event.GameEventBus
|
||||||
import eventDemo.business.event.event.CardIsPlayedEvent
|
import eventDemo.business.event.event.CardIsPlayedEvent
|
||||||
@@ -35,9 +36,14 @@ class PlayerNotificationEventListener(
|
|||||||
fun startListening(
|
fun startListening(
|
||||||
outgoingNotification: (Notification) -> Unit,
|
outgoingNotification: (Notification) -> Unit,
|
||||||
currentPlayer: Player,
|
currentPlayer: Player,
|
||||||
|
gameId: GameId,
|
||||||
) {
|
) {
|
||||||
eventBus.subscribe { event: GameEvent ->
|
eventBus.subscribe { event: GameEvent ->
|
||||||
withLoggingContext("event" to event.toString()) {
|
withLoggingContext("event" to event.toString()) {
|
||||||
|
if (event.aggregateId != gameId) {
|
||||||
|
return@subscribe
|
||||||
|
}
|
||||||
|
|
||||||
val currentState = gameStateRepository.getUntil(event)
|
val currentState = gameStateRepository.getUntil(event)
|
||||||
|
|
||||||
fun Notification.send() {
|
fun Notification.send() {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import eventDemo.business.event.projection.GameState
|
|||||||
import eventDemo.business.event.projection.GameStateRepository
|
import eventDemo.business.event.projection.GameStateRepository
|
||||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
import io.github.oshai.kotlinlogging.withLoggingContext
|
import io.github.oshai.kotlinlogging.withLoggingContext
|
||||||
|
import java.util.concurrent.ConcurrentSkipListSet
|
||||||
|
|
||||||
class ReactionEventListener(
|
class ReactionEventListener(
|
||||||
private val eventBus: GameEventBus,
|
private val eventBus: GameEventBus,
|
||||||
@@ -19,11 +20,13 @@ class ReactionEventListener(
|
|||||||
) {
|
) {
|
||||||
companion object Config {
|
companion object Config {
|
||||||
const val DEFAULT_PRIORITY = -1000
|
const val DEFAULT_PRIORITY = -1000
|
||||||
|
val registeredListeners = ConcurrentSkipListSet<GameEventBus>()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val logger = KotlinLogging.logger { }
|
private val logger = KotlinLogging.logger { }
|
||||||
|
|
||||||
fun init() {
|
fun init() {
|
||||||
|
if (registeredListeners.add(eventBus)) {
|
||||||
eventBus.subscribe(priority) { event: GameEvent ->
|
eventBus.subscribe(priority) { event: GameEvent ->
|
||||||
withLoggingContext("event" to event.toString()) {
|
withLoggingContext("event" to event.toString()) {
|
||||||
val state = gameStateRepository.getUntil(event)
|
val state = gameStateRepository.getUntil(event)
|
||||||
@@ -31,6 +34,9 @@ class ReactionEventListener(
|
|||||||
sendWinnerEvent(state)
|
sendWinnerEvent(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
logger.error { "${this::class.java.simpleName} is already init for this bus" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sendStartGameEvent(
|
private fun sendStartGameEvent(
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import io.ktor.server.plugins.cors.routing.CORS
|
|||||||
import io.ktor.server.plugins.statuspages.StatusPages
|
import io.ktor.server.plugins.statuspages.StatusPages
|
||||||
import io.ktor.server.resources.Resources
|
import io.ktor.server.resources.Resources
|
||||||
import io.ktor.server.response.respondText
|
import io.ktor.server.response.respondText
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
fun Application.configureHttpRouting() {
|
fun Application.configureHttpRouting() {
|
||||||
install(CORS) {
|
install(CORS) {
|
||||||
@@ -38,13 +39,14 @@ class BadRequestException(
|
|||||||
val httpError: HttpErrorBadRequest,
|
val httpError: HttpErrorBadRequest,
|
||||||
) : Exception()
|
) : Exception()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
class HttpErrorBadRequest(
|
class HttpErrorBadRequest(
|
||||||
statusCode: HttpStatusCode,
|
val title: String = HttpStatusCode.BadRequest.description,
|
||||||
val title: String = statusCode.description,
|
val invalidParams: List<InvalidParam> = emptyList(),
|
||||||
val invalidParams: List<InvalidParam>,
|
|
||||||
) {
|
) {
|
||||||
val statusCode: Int = statusCode.value
|
val statusCode: Int = HttpStatusCode.BadRequest.value
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class InvalidParam(
|
data class InvalidParam(
|
||||||
val name: String,
|
val name: String,
|
||||||
val reason: String,
|
val reason: String,
|
||||||
|
|||||||
@@ -34,10 +34,19 @@ class GameCommandHandlerTest :
|
|||||||
val channelCommand = Channel<GameCommand>(Channel.BUFFERED)
|
val channelCommand = Channel<GameCommand>(Channel.BUFFERED)
|
||||||
val channelNotification = Channel<Notification>(Channel.BUFFERED)
|
val channelNotification = Channel<Notification>(Channel.BUFFERED)
|
||||||
ReactionEventListener(get(), get(), get()).init()
|
ReactionEventListener(get(), get(), get()).init()
|
||||||
notificationListener.startListening({ channelNotification.trySendBlocking(it) }, player)
|
notificationListener.startListening(
|
||||||
|
{ channelNotification.trySendBlocking(it) },
|
||||||
|
player,
|
||||||
|
gameId,
|
||||||
|
)
|
||||||
|
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
commandHandler.handle(player, channelCommand, channelNotification)
|
commandHandler.handle(
|
||||||
|
player,
|
||||||
|
gameId,
|
||||||
|
channelCommand,
|
||||||
|
channelNotification,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
IWantToJoinTheGameCommand(IWantToJoinTheGameCommand.Payload(gameId, player)).also { sendCommand ->
|
IWantToJoinTheGameCommand(IWantToJoinTheGameCommand.Payload(gameId, player)).also { sendCommand ->
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class GameSimulationTest :
|
|||||||
test("Simulation of a game") {
|
test("Simulation of a game") {
|
||||||
withTimeout(2.seconds) {
|
withTimeout(2.seconds) {
|
||||||
disableShuffleDeck()
|
disableShuffleDeck()
|
||||||
val id = GameId()
|
val gameId = GameId()
|
||||||
val player1 = Player(name = "Nikola")
|
val player1 = Player(name = "Nikola")
|
||||||
val player2 = Player(name = "Einstein")
|
val player2 = Player(name = "Einstein")
|
||||||
val channelCommand1 = Channel<GameCommand>(Channel.BUFFERED)
|
val channelCommand1 = Channel<GameCommand>(Channel.BUFFERED)
|
||||||
@@ -61,7 +61,7 @@ class GameSimulationTest :
|
|||||||
|
|
||||||
val player1Job =
|
val player1Job =
|
||||||
launch {
|
launch {
|
||||||
IWantToJoinTheGameCommand(IWantToJoinTheGameCommand.Payload(id, player1)).also { sendCommand ->
|
IWantToJoinTheGameCommand(IWantToJoinTheGameCommand.Payload(gameId, player1)).also { sendCommand ->
|
||||||
channelCommand1.send(sendCommand)
|
channelCommand1.send(sendCommand)
|
||||||
channelNotification1.receive().let {
|
channelNotification1.receive().let {
|
||||||
assertIs<CommandSuccessNotification>(it).commandId shouldBeEqual sendCommand.id
|
assertIs<CommandSuccessNotification>(it).commandId shouldBeEqual sendCommand.id
|
||||||
@@ -74,7 +74,7 @@ class GameSimulationTest :
|
|||||||
channelNotification1.receive().let {
|
channelNotification1.receive().let {
|
||||||
assertIs<PlayerAsJoinTheGameNotification>(it).player shouldBeEqual player2
|
assertIs<PlayerAsJoinTheGameNotification>(it).player shouldBeEqual player2
|
||||||
}
|
}
|
||||||
IamReadyToPlayCommand(IamReadyToPlayCommand.Payload(id, player1)).also { sendCommand ->
|
IamReadyToPlayCommand(IamReadyToPlayCommand.Payload(gameId, player1)).also { sendCommand ->
|
||||||
channelCommand1.send(sendCommand)
|
channelCommand1.send(sendCommand)
|
||||||
channelNotification1.receive().let {
|
channelNotification1.receive().let {
|
||||||
assertIs<CommandSuccessNotification>(it).commandId shouldBeEqual sendCommand.id
|
assertIs<CommandSuccessNotification>(it).commandId shouldBeEqual sendCommand.id
|
||||||
@@ -94,7 +94,7 @@ class GameSimulationTest :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IWantToPlayCardCommand(IWantToPlayCardCommand.Payload(id, player1, player1Hand.first())).also { sendCommand ->
|
IWantToPlayCardCommand(IWantToPlayCardCommand.Payload(gameId, player1, player1Hand.first())).also { sendCommand ->
|
||||||
channelCommand1.send(sendCommand)
|
channelCommand1.send(sendCommand)
|
||||||
channelNotification1.receive().let {
|
channelNotification1.receive().let {
|
||||||
assertIs<CommandSuccessNotification>(it).commandId shouldBeEqual sendCommand.id
|
assertIs<CommandSuccessNotification>(it).commandId shouldBeEqual sendCommand.id
|
||||||
@@ -118,7 +118,7 @@ class GameSimulationTest :
|
|||||||
val player2Job =
|
val player2Job =
|
||||||
launch {
|
launch {
|
||||||
delay(100)
|
delay(100)
|
||||||
IWantToJoinTheGameCommand(IWantToJoinTheGameCommand.Payload(id, player2)).also { sendCommand ->
|
IWantToJoinTheGameCommand(IWantToJoinTheGameCommand.Payload(gameId, player2)).also { sendCommand ->
|
||||||
channelCommand2.send(sendCommand)
|
channelCommand2.send(sendCommand)
|
||||||
channelNotification2.receive().let {
|
channelNotification2.receive().let {
|
||||||
assertIs<CommandSuccessNotification>(it).commandId shouldBeEqual sendCommand.id
|
assertIs<CommandSuccessNotification>(it).commandId shouldBeEqual sendCommand.id
|
||||||
@@ -132,7 +132,7 @@ class GameSimulationTest :
|
|||||||
assertIs<PlayerWasReadyNotification>(it).player shouldBeEqual player1
|
assertIs<PlayerWasReadyNotification>(it).player shouldBeEqual player1
|
||||||
}
|
}
|
||||||
|
|
||||||
IamReadyToPlayCommand(IamReadyToPlayCommand.Payload(id, player2)).also { sendCommand ->
|
IamReadyToPlayCommand(IamReadyToPlayCommand.Payload(gameId, player2)).also { sendCommand ->
|
||||||
channelCommand2.send(sendCommand)
|
channelCommand2.send(sendCommand)
|
||||||
channelNotification2.receive().let {
|
channelNotification2.receive().let {
|
||||||
assertIs<CommandSuccessNotification>(it).commandId shouldBeEqual sendCommand.id
|
assertIs<CommandSuccessNotification>(it).commandId shouldBeEqual sendCommand.id
|
||||||
@@ -162,7 +162,7 @@ class GameSimulationTest :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IWantToPlayCardCommand(IWantToPlayCardCommand.Payload(id, player2, player2Hand.first())).also { sendCommand ->
|
IWantToPlayCardCommand(IWantToPlayCardCommand.Payload(gameId, player2, player2Hand.first())).also { sendCommand ->
|
||||||
channelCommand2.send(sendCommand)
|
channelCommand2.send(sendCommand)
|
||||||
channelNotification2.receive().let {
|
channelNotification2.receive().let {
|
||||||
assertIs<CommandSuccessNotification>(it).commandId shouldBeEqual sendCommand.id
|
assertIs<CommandSuccessNotification>(it).commandId shouldBeEqual sendCommand.id
|
||||||
@@ -175,14 +175,14 @@ class GameSimulationTest :
|
|||||||
val eventStore by inject<GameEventStore>()
|
val eventStore by inject<GameEventStore>()
|
||||||
val playerNotificationListener by inject<PlayerNotificationEventListener>()
|
val playerNotificationListener by inject<PlayerNotificationEventListener>()
|
||||||
ReactionEventListener(get(), get(), get()).init()
|
ReactionEventListener(get(), get(), get()).init()
|
||||||
playerNotificationListener.startListening({ channelNotification1.trySendBlocking(it) }, player1)
|
playerNotificationListener.startListening({ channelNotification1.trySendBlocking(it) }, player1, gameId)
|
||||||
playerNotificationListener.startListening({ channelNotification2.trySendBlocking(it) }, player2)
|
playerNotificationListener.startListening({ channelNotification2.trySendBlocking(it) }, player2, gameId)
|
||||||
|
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
commandHandler.handle(player1, channelCommand1, channelNotification1)
|
commandHandler.handle(player1, gameId, channelCommand1, channelNotification1)
|
||||||
}
|
}
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
commandHandler.handle(player2, channelCommand2, channelNotification2)
|
commandHandler.handle(player2, gameId, channelCommand2, channelNotification2)
|
||||||
}
|
}
|
||||||
|
|
||||||
joinAll(player1Job, player2Job)
|
joinAll(player1Job, player2Job)
|
||||||
@@ -192,9 +192,9 @@ class GameSimulationTest :
|
|||||||
eventStore = eventStore,
|
eventStore = eventStore,
|
||||||
initialStateBuilder = { aggregateId: GameId -> GameState(aggregateId) },
|
initialStateBuilder = { aggregateId: GameId -> GameState(aggregateId) },
|
||||||
applyToProjection = GameState::apply,
|
applyToProjection = GameState::apply,
|
||||||
).getLast(id)
|
).getLast(gameId)
|
||||||
|
|
||||||
state.aggregateId shouldBeEqual id
|
state.aggregateId shouldBeEqual gameId
|
||||||
assertTrue(state.isStarted)
|
assertTrue(state.isStarted)
|
||||||
state.players shouldBeEqual setOf(player1, player2)
|
state.players shouldBeEqual setOf(player1, player2)
|
||||||
state.readyPlayers shouldBeEqual setOf(player1, player2)
|
state.readyPlayers shouldBeEqual setOf(player1, player2)
|
||||||
|
|||||||
@@ -79,8 +79,8 @@ class GameStateRouteTest :
|
|||||||
GameStartedEvent.new(
|
GameStartedEvent.new(
|
||||||
gameId,
|
gameId,
|
||||||
setOf(player1, player2),
|
setOf(player1, player2),
|
||||||
shuffleIsDisabled = true,
|
|
||||||
it,
|
it,
|
||||||
|
shuffleIsDisabled = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
delay(100)
|
delay(100)
|
||||||
|
|||||||
Reference in New Issue
Block a user