-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
依據jwt subject is user identity修正 根據第三次 code review 修正 根據第二次 code review 修正 根據第一次 code review 修正 實作取得房間資訊
- Loading branch information
Ted
committed
Jul 29, 2023
1 parent
6e1a004
commit 5d31a08
Showing
7 changed files
with
179 additions
and
6 deletions.
There are no files selected for viewing
41 changes: 41 additions & 0 deletions
41
application/src/main/kotlin/tw/waterballsa/gaas/application/usecases/GetRoomUsecase.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package tw.waterballsa.gaas.application.usecases | ||
|
||
import tw.waterballsa.gaas.application.eventbus.EventBus | ||
import tw.waterballsa.gaas.application.repositories.RoomRepository | ||
import tw.waterballsa.gaas.application.repositories.UserRepository | ||
import tw.waterballsa.gaas.domain.Room | ||
import tw.waterballsa.gaas.domain.Room.Player | ||
import tw.waterballsa.gaas.exceptions.PlatformException | ||
import tw.waterballsa.gaas.exceptions.enums.PlatformError.PLAYER_NOT_IN_ROOM_ERROR | ||
import javax.inject.Named | ||
|
||
@Named | ||
class GetRoomUsecase( | ||
roomRepository: RoomRepository, | ||
userRepository: UserRepository, | ||
private val eventBus: EventBus, | ||
) : AbstractRoomUseCase(roomRepository, userRepository) { | ||
fun execute(request: Request, presenter: Presenter) { | ||
with(request) { | ||
val room = findRoomById(roomId) | ||
val player = findPlayerByIdentity(userIdentity) | ||
room.validatePlayerInRoom(player.id) | ||
presenter.present(room) | ||
} | ||
} | ||
|
||
private fun Room.validatePlayerInRoom(playerId: Player.Id) { | ||
if (!hasPlayer(playerId)) { | ||
throw PlatformException(PLAYER_NOT_IN_ROOM_ERROR, "Player(${playerId.value}) is not in the room(${roomId!!.value}).") | ||
} | ||
} | ||
|
||
data class Request( | ||
val roomId: String, | ||
val userIdentity: String | ||
) | ||
|
||
interface Presenter { | ||
fun present(room: Room) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
spring/src/main/kotlin/tw/waterballsa/gaas/spring/controllers/presenter/GetRoomPresenter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package tw.waterballsa.gaas.spring.controllers.presenter | ||
|
||
import tw.waterballsa.gaas.application.usecases.GetRoomUsecase | ||
import tw.waterballsa.gaas.domain.GameRegistration | ||
import tw.waterballsa.gaas.domain.Room | ||
import tw.waterballsa.gaas.spring.controllers.viewmodel.GetRoomViewModel | ||
|
||
class GetRoomPresenter : GetRoomUsecase.Presenter { | ||
lateinit var viewModel: GetRoomViewModel | ||
private set | ||
|
||
override fun present(room: Room) { | ||
viewModel = room.toViewModel() | ||
} | ||
|
||
} | ||
|
||
private fun Room.toViewModel(): GetRoomViewModel = | ||
GetRoomViewModel( | ||
id = roomId!!.value, | ||
name = name, | ||
game = game.toViewModel(), | ||
host = host.toViewModel(), | ||
players = players.map { it.toViewModel() }, | ||
maxPlayers = maxPlayers, | ||
minPlayers = minPlayers, | ||
currentPlayers = players.size, | ||
isLocked = isLocked, | ||
status = status.toString() | ||
) | ||
|
||
private fun GameRegistration.toViewModel(): GetRoomViewModel.Game = | ||
GetRoomViewModel.Game(id!!.value, displayName) | ||
|
||
private fun Room.Player.toViewModel(): GetRoomViewModel.Player = | ||
GetRoomViewModel.Player(id.value, nickname, readiness) |
18 changes: 18 additions & 0 deletions
18
spring/src/main/kotlin/tw/waterballsa/gaas/spring/controllers/viewmodel/GetRoomViewModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package tw.waterballsa.gaas.spring.controllers.viewmodel | ||
|
||
data class GetRoomViewModel( | ||
val id: String, | ||
val name: String, | ||
val game: Game, | ||
val host: Player, | ||
val players: List<Player>, | ||
val maxPlayers: Int, | ||
val minPlayers: Int, | ||
val currentPlayers: Int, | ||
val isLocked: Boolean, | ||
val status: String | ||
) { | ||
data class Game(val id: String, val name: String) | ||
|
||
data class Player(val id: String, val nickname: String, val isReady: Boolean) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -327,7 +327,7 @@ class RoomControllerTest @Autowired constructor( | |
"winner0033", "google-oauth2|200000000000000000000" | ||
).toRoomPlayer() | ||
|
||
givenHostAndPlayersAreInTheRoom(host, playerB, playerC) | ||
givenHostAndPlayersJoinedTheRoom(host, playerB, playerC) | ||
.whenUserLeaveTheRoom(userA) | ||
.thenPlayerShouldBeNotInRoomAndHostIsChanged(host) | ||
} | ||
|
@@ -360,6 +360,33 @@ class RoomControllerTest @Autowired constructor( | |
.thenShouldFail("Player(${userB.id!!.value}) has joined another room.") | ||
} | ||
|
||
@Test | ||
fun giveHostAndPlayerBJoinedRoomC_WhenHostGetRoomC_ThenShouldGetRoomCSuccessfully() { | ||
val userA = testUser | ||
val host = userA.toRoomPlayer() | ||
val playerB = createUser( | ||
"2", "[email protected]", | ||
"winner1122", "google-oauth2|100000000000000000000" | ||
).toRoomPlayer() | ||
|
||
givenHostAndPlayersJoinedTheRoom(host, playerB) | ||
.whenUserGetTheRoom(userA) | ||
.thenGetRoomSuccessfully() | ||
} | ||
|
||
@Test | ||
fun giveUserANotJoinedRoomB_WhenUserAGetRoomB_ThenShouldFail() { | ||
val userA = testUser | ||
val host = createUser( | ||
"2", "[email protected]", | ||
"winner1122", "google-oauth2|100000000000000000000" | ||
).toRoomPlayer() | ||
|
||
givenHostAndPlayersJoinedTheRoom(host) | ||
.whenUserGetTheRoom(userA) | ||
.thenShouldFail("Player(${userA.id!!.value}) is not in the room(${testRoom.roomId!!.value}).") | ||
} | ||
|
||
private fun TestGetRoomsRequest.whenUserAVisitLobby(joinUser: User): ResultActions = | ||
mockMvc.perform( | ||
get("/rooms") | ||
|
@@ -429,7 +456,7 @@ class RoomControllerTest @Autowired constructor( | |
return testRoom | ||
} | ||
|
||
private fun givenHostAndPlayersAreInTheRoom(host: Player, vararg players: Player): Room { | ||
private fun givenHostAndPlayersJoinedTheRoom(host: Player, vararg players: Player): Room { | ||
val combinedPlayers = (listOf(host) + players).toMutableList() | ||
testRoom = createRoom(host, combinedPlayers) | ||
return testRoom | ||
|
@@ -451,6 +478,14 @@ class RoomControllerTest @Autowired constructor( | |
return leaveRoom(leaveUser) | ||
} | ||
|
||
private fun Room.whenUserGetTheRoom(user: User) = getRoom(user) | ||
|
||
private fun getRoom(user: User): ResultActions = | ||
mockMvc.perform( | ||
get("/rooms/${testRoom.roomId!!.value}") | ||
.withJwt(user.toJwt()) | ||
) | ||
|
||
private fun ResultActions.thenCreateRoomSuccessfully() { | ||
val roomView = getBody(CreateRoomViewModel::class.java) | ||
val room = roomRepository.findById(roomView.id)!! | ||
|
@@ -500,6 +535,33 @@ class RoomControllerTest @Autowired constructor( | |
|
||
private fun createUser(user: User): User = userRepository.createUser(user) | ||
|
||
private fun ResultActions.thenGetRoomSuccessfully() { | ||
val room = roomRepository.findById(testRoom.roomId!!)!! | ||
room.let { | ||
andExpect(status().isOk) | ||
.andExpect(jsonPath("$.id").exists()) | ||
.andExpect(jsonPath("$.id").value(it.roomId!!.value)) | ||
.andExpect(jsonPath("$.name").value(it.name)) | ||
.andExpect(jsonPath("$.game.id").value(it.game.id!!.value)) | ||
.andExpect(jsonPath("$.game.name").value(it.game.displayName)) | ||
.andExpect(jsonPath("$.host.id").value(it.host.id!!.value)) | ||
.andExpect(jsonPath("$.host.nickname").value(it.host.nickname)) | ||
.andExpect(jsonPath("$.host.isReady").value(it.host.readiness)) | ||
.andExpect(jsonPath("$.isLocked").value(!it.password.isNullOrEmpty())) | ||
.andExpect(jsonPath("$.status").value(it.status.toString())) | ||
.andExpect(jsonPath("$.currentPlayers").value(2)) | ||
.andExpect(jsonPath("$.minPlayers").value(it.minPlayers)) | ||
.andExpect(jsonPath("$.maxPlayers").value(it.maxPlayers)) | ||
.andExpect(jsonPath("$.players").isArray()) | ||
|
||
it.players.forEachIndexed { index, player -> | ||
andExpect(jsonPath("$.players[$index].id").value(player.id!!.value)) | ||
.andExpect(jsonPath("$.players[$index].nickname").value(player.nickname)) | ||
.andExpect(jsonPath("$.players[$index].isReady").value(player.readiness)) | ||
} | ||
} | ||
} | ||
|
||
private fun registerGame(): GameRegistration = gameRegistrationRepository.registerGame( | ||
GameRegistration( | ||
uniqueName = "Mahjong-python", | ||
|
@@ -585,9 +647,6 @@ class RoomControllerTest @Autowired constructor( | |
private fun User.toRoomPlayer(): Player = | ||
Player(Player.Id(id!!.value), nickname) | ||
|
||
private fun Room.hasPlayer(playerId: Player.Id): Boolean = | ||
players.any { it.id == playerId } | ||
|
||
private fun Room.isHost(playerId: Player.Id): Boolean = | ||
host.id == playerId | ||
} |