From 1e928d83a333542ca6de793fe5a6c5a2bf50d354 Mon Sep 17 00:00:00 2001 From: KazeNoYumeX Date: Thu, 21 Mar 2024 16:46:03 +0800 Subject: [PATCH] Fix: Removed the game ID that is no longer needed from PlayCard and TransmitIntelligence --- .../delivery/http/v1/player_handler.go | 8 +- .../mysql/player_card_repository.go | 8 +- .../repository/player_card_repository.go | 4 +- Backend/service/service/player_service.go | 8 +- Backend/tests/e2e/game_api_test.go | 8 +- Backend/tests/e2e/player_api_test.go | 226 +++++++++--------- 6 files changed, 127 insertions(+), 135 deletions(-) diff --git a/Backend/service/delivery/http/v1/player_handler.go b/Backend/service/delivery/http/v1/player_handler.go index 4f8ba06..45832a2 100644 --- a/Backend/service/delivery/http/v1/player_handler.go +++ b/Backend/service/delivery/http/v1/player_handler.go @@ -70,9 +70,7 @@ func (p *PlayerHandler) PlayCard(c *gin.Context) { "next_player": game.CurrentPlayerID, } - c.JSON(http.StatusOK, gin.H{ - "result": true, - }) + c.JSON(http.StatusOK, gin.H{}) } // TransmitIntelligence godoc @@ -104,13 +102,13 @@ func (p *PlayerHandler) TransmitIntelligence(c *gin.Context) { } // Check card_id exists in player_cards - exist, err := p.playerService.CheckPlayerCardExist(c, playerId, player.GameID, req.CardID) + exist, err := p.playerService.CheckPlayerCardExist(c, playerId, req.CardID) if err != nil || !exist { c.JSON(http.StatusInternalServerError, gin.H{"message": "Card not found"}) return } - ret, err := p.playerService.TransmitIntelligenceCard(c, playerId, player.GameID, req.CardID) + ret, err := p.playerService.TransmitIntelligenceCard(c, playerId, req.CardID) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"message": err.Error()}) return diff --git a/Backend/service/repository/mysql/player_card_repository.go b/Backend/service/repository/mysql/player_card_repository.go index 9d96224..ac77643 100644 --- a/Backend/service/repository/mysql/player_card_repository.go +++ b/Backend/service/repository/mysql/player_card_repository.go @@ -40,10 +40,10 @@ func (p PlayerCardRepository) DeletePlayerCard(ctx context.Context, id uint) err return nil } -func (p PlayerCardRepository) DeletePlayerCardByPlayerIdAndCardId(ctx context.Context, playerId uint, gameId uint, cardId uint) (bool, error) { +func (p PlayerCardRepository) DeletePlayerCardByPlayerIdAndCardId(ctx context.Context, playerId uint, cardId uint) (bool, error) { card := new(repository.PlayerCard) - result := p.db.Delete(&card, "player_id = ? AND game_id = ? AND card_id = ?", playerId, gameId, cardId) + result := p.db.Delete(&card, "player_id = ? AND card_id = ?", playerId, cardId) if result.Error != nil { return false, result.Error } @@ -51,9 +51,9 @@ func (p PlayerCardRepository) DeletePlayerCardByPlayerIdAndCardId(ctx context.Co return true, nil } -func (p *PlayerCardRepository) ExistPlayerCardByPlayerIdAndCardId(ctx context.Context, playerId uint, gameId uint, cardId uint) (bool, error) { +func (p *PlayerCardRepository) ExistPlayerCardByPlayerIdAndCardId(ctx context.Context, playerId uint, cardId uint) (bool, error) { var card repository.PlayerCard - result := p.db.First(&card, "player_id = ? AND game_id = ? AND card_id = ?", playerId, gameId, cardId) + result := p.db.First(&card, "player_id = ? AND card_id = ?", playerId, cardId) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { return false, nil diff --git a/Backend/service/repository/player_card_repository.go b/Backend/service/repository/player_card_repository.go index 8cd6d2e..398a0c2 100644 --- a/Backend/service/repository/player_card_repository.go +++ b/Backend/service/repository/player_card_repository.go @@ -20,7 +20,7 @@ type PlayerCardRepository interface { GetPlayerCardsByGameId(ctx context.Context, id uint) ([]*PlayerCard, error) CreatePlayerCard(ctx context.Context, card *PlayerCard) (*PlayerCard, error) DeletePlayerCard(ctx context.Context, id uint) error - DeletePlayerCardByPlayerIdAndCardId(ctx context.Context, playerId uint, gameId uint, cardId uint) (bool, error) - ExistPlayerCardByPlayerIdAndCardId(ctx context.Context, playerId uint, gameId uint, cardId uint) (bool, error) + DeletePlayerCardByPlayerIdAndCardId(ctx context.Context, playerId uint, cardId uint) (bool, error) + ExistPlayerCardByPlayerIdAndCardId(ctx context.Context, playerId uint, cardId uint) (bool, error) GetPlayerCards(ctx context.Context, playerCard *PlayerCard) (*[]PlayerCard, error) } diff --git a/Backend/service/service/player_service.go b/Backend/service/service/player_service.go index c19d9ad..8aec416 100644 --- a/Backend/service/service/player_service.go +++ b/Backend/service/service/player_service.go @@ -89,8 +89,8 @@ func (p *PlayerService) CanPlayCard(c context.Context, player *repository.Player return true, nil } -func (p *PlayerService) CheckPlayerCardExist(c context.Context, playerId uint, gameId uint, cardId uint) (bool, error) { - exist, err := p.PlayerCardRepo.ExistPlayerCardByPlayerIdAndCardId(c, playerId, gameId, cardId) +func (p *PlayerService) CheckPlayerCardExist(c context.Context, playerId uint, cardId uint) (bool, error) { + exist, err := p.PlayerCardRepo.ExistPlayerCardByPlayerIdAndCardId(c, playerId, cardId) if err != nil { return false, err @@ -174,7 +174,7 @@ func (p *PlayerService) PlayCard(c context.Context, playerId uint, cardId uint) return game, &handCard.Card, nil } -func (p *PlayerService) TransmitIntelligenceCard(c context.Context, playerId uint, gameId uint, cardId uint) (bool, error) { +func (p *PlayerService) TransmitIntelligenceCard(c context.Context, playerId uint, cardId uint) (bool, error) { player, err := p.PlayerRepo.GetPlayerWithGamePlayersAndPlayerCardsCard(c, playerId) if err != nil { return false, err @@ -190,7 +190,7 @@ func (p *PlayerService) TransmitIntelligenceCard(c context.Context, playerId uin return false, err } - ret, err := p.PlayerCardRepo.DeletePlayerCardByPlayerIdAndCardId(c, playerId, gameId, cardId) + ret, err := p.PlayerCardRepo.DeletePlayerCardByPlayerIdAndCardId(c, playerId, cardId) if err != nil { return false, err } diff --git a/Backend/tests/e2e/game_api_test.go b/Backend/tests/e2e/game_api_test.go index 4348263..4e54920 100644 --- a/Backend/tests/e2e/game_api_test.go +++ b/Backend/tests/e2e/game_api_test.go @@ -20,7 +20,7 @@ import ( func (suite *IntegrationTestSuite) TestStartGameE2E() { // Set the cards - seeders.SeederCards(suite.db) + seeders.OnlyCardsRun(suite.db) api := "/api/v1/games" @@ -50,7 +50,7 @@ func (suite *IntegrationTestSuite) TestStartGameE2E() { }) suite.T().Run("it can fail when player count less than 3", func(t *testing.T) { - num := rand.Intn(3) + num := rand.Intn(2) + 1 var players []request.PlayerInfo for i := 0; i < num; i++ { @@ -135,13 +135,13 @@ func (suite *IntegrationTestSuite) TestStartGameE2E() { assert.Equal(t, url, resBody["url"]) // Assert Game and Players - game := new(repository.Game) + game := &repository.Game{} _ = suite.db.First(&game, "id = ?", 1) assert.Equal(t, roomID, game.RoomID) assert.Equal(t, enums.ActionCardStage, game.Status) - gamePlayers := new([]repository.Player) + gamePlayers := &[]repository.Player{} _ = suite.db.Find(&gamePlayers, "game_id = ?", game.ID) assert.Equal(t, num, len(*gamePlayers)) diff --git a/Backend/tests/e2e/player_api_test.go b/Backend/tests/e2e/player_api_test.go index 7fdde4c..37d82c7 100644 --- a/Backend/tests/e2e/player_api_test.go +++ b/Backend/tests/e2e/player_api_test.go @@ -1,9 +1,6 @@ package e2e import ( - "context" - "encoding/json" - "io" "math" "math/rand" "net/http" @@ -12,7 +9,8 @@ import ( "testing" "github.com/Game-as-a-Service/The-Message/enums" - "github.com/Game-as-a-Service/The-Message/service/request" + "github.com/Game-as-a-Service/The-Message/service/repository" + "github.com/Game-as-a-Service/The-Message/utils" "github.com/go-faker/faker/v4" "github.com/stretchr/testify/assert" ) @@ -20,100 +18,117 @@ import ( func (suite *IntegrationTestSuite) TestPlayCardE2E() { // Given api := "/api/v1/players/{player_id}/player-cards" - game, _ := suite.gameServ.InitGame(context.TODO()) + + // Get all cards + var cards []*repository.Card + _ = suite.db.Find(&cards) + + // Fake game data + game := &repository.Game{ + RoomID: faker.UUIDDigit(), + Status: enums.GameStart, + Players: []repository.Player{}, + } // Fake player count random 1~3 playerCount := rand.Intn(3) + 1 // Fake players data - var players []request.PlayerInfo for i := 0; i < playerCount; i++ { - player := request.PlayerInfo{ - ID: faker.UUIDDigit(), - Name: faker.FirstName(), + player := repository.Player{ + UserID: faker.UUIDDigit(), + Name: faker.FirstName(), + PlayerCards: []repository.PlayerCard{}, } - players = append(players, player) - } - // Fake game data - createGameRequest := request.CreateGameRequest{ - Players: players, + // Each player gets 3 cards + for j := 0; j < 3; j++ { + player.PlayerCards = append(player.PlayerCards, repository.PlayerCard{ + CardID: cards[i*3+j].ID, + Type: "hand", + }) + } + game.Players = append(game.Players, player) } - _ = suite.playerServ.InitPlayers(context.TODO(), game, createGameRequest) - _ = suite.gameServ.InitDeck(context.TODO(), game) - _ = suite.gameServ.DrawCardsForAllPlayers(context.TODO(), game) + _ = suite.db.Create(&game) - playerId := rand.Intn(playerCount) + 1 - - // Get player's card - cards, _ := suite.playerRepo.GetPlayerWithPlayerCards(context.TODO(), playerId) + id := rand.Intn(playerCount) + player := game.Players[id] // Random card id - num := rand.Intn(len(cards.PlayerCards)) - cardId := cards.PlayerCards[num].CardId + num := rand.Intn(len(player.PlayerCards)) + cardId := player.PlayerCards[num].CardID // Set player to current player - suite.gameServ.UpdateCurrentPlayer(context.TODO(), game, playerId) + game.CurrentPlayerID = player.ID + _ = suite.db.Save(&game) - url := strings.ReplaceAll(api, "{player_id}", strconv.Itoa(playerId)) - req := PlayCardRequest{CardId: cardId} - reqBody, _ := json.Marshal(req) + url := strings.ReplaceAll(api, "{player_id}", strconv.Itoa(int(player.ID))) - res := suite.requestJson(url, reqBody, http.MethodPost) + req := utils.RequestToJsonBody(PlayCardRequest{CardID: cardId}) - // Convert response body from json to map - resBodyAsByteArray, _ := io.ReadAll(res.Body) - resBody := make(map[string]interface{}) - _ = json.Unmarshal(resBodyAsByteArray, &resBody) + res := suite.requestJson(url, req, http.MethodPost) // Then - assert.Equal(suite.T(), 200, res.StatusCode) + assert.Equal(suite.T(), http.StatusOK, res.StatusCode) + + var count int64 + playerCard := &repository.PlayerCard{} + _ = suite.db.Model(&playerCard).Where("player_id = ?", player.ID).Count(&count) - player, _ := suite.playerRepo.GetPlayerWithPlayerCards(context.TODO(), playerId) - assert.Equal(suite.T(), len(cards.PlayerCards)-1, len(player.PlayerCards)) + PlayerCards := int64(len(player.PlayerCards) - 1) + assert.Equal(suite.T(), PlayerCards, count) } func (suite *IntegrationTestSuite) TestTransmitIntelligenceE2E() { api := "/api/v1/player/{player_id}/transmit-intelligence" - game, _ := suite.gameServ.InitGame(context.TODO()) + + // Get all cards + var cards []*repository.Card + _ = suite.db.Find(&cards) + + // Fake game data + game := &repository.Game{ + RoomID: faker.UUIDDigit(), + Status: enums.GameStart, + Players: []repository.Player{}, + } // Fake player count random 1~3 playerCount := rand.Intn(3) + 1 // Fake players data - var players []request.PlayerInfo for i := 0; i < playerCount; i++ { - player := request.PlayerInfo{ - ID: faker.UUIDDigit(), - Name: faker.FirstName(), + player := repository.Player{ + UserID: faker.UUIDDigit(), + Name: faker.FirstName(), + PlayerCards: []repository.PlayerCard{}, } - players = append(players, player) - } - // Fake game data - createGameRequest := request.CreateGameRequest{ - Players: players, + // Each player gets 3 cards + for j := 0; j < 3; j++ { + player.PlayerCards = append(player.PlayerCards, repository.PlayerCard{ + CardID: cards[i*3+j].ID, + Type: "hand", + }) + } + game.Players = append(game.Players, player) } - _ = suite.playerServ.InitPlayers(context.TODO(), game, createGameRequest) - _ = suite.gameServ.InitDeck(context.TODO(), game) - _ = suite.gameServ.DrawCardsForAllPlayers(context.TODO(), game) + _ = suite.db.Create(&game) suite.T().Run("it can validate card id", func(t *testing.T) { playerId := rand.Intn(playerCount) + 1 // Request only intelligence type url := strings.ReplaceAll(api, "{player_id}", strconv.Itoa(playerId)) - req := PlayCardRequest{} - reqBody, _ := json.Marshal(req) + req := utils.RequestToJsonBody(PlayCardRequest{}) - res := suite.requestJson(url, reqBody, http.MethodPost) + res := suite.requestJson(url, req, http.MethodPost) // Convert response body from json to map - resBodyAsByteArray, _ := io.ReadAll(res.Body) - resBody := make(map[string]interface{}) - _ = json.Unmarshal(resBodyAsByteArray, &resBody) + resBody := utils.JsonBodyToMap(res) assert.Equal(t, http.StatusInternalServerError, res.StatusCode) assert.Equal(t, "Card not found", resBody["message"]) @@ -121,18 +136,15 @@ func (suite *IntegrationTestSuite) TestTransmitIntelligenceE2E() { suite.T().Run("it can fail when player not found", func(t *testing.T) { playerId := math.MaxInt32 - cardId := rand.Intn(playerCount) + cardId := uint(rand.Intn(playerCount)) url := strings.ReplaceAll(api, "{player_id}", strconv.Itoa(playerId)) - req := PlayCardRequest{CardId: cardId} - reqBody, _ := json.Marshal(req) + req := utils.RequestToJsonBody(PlayCardRequest{CardID: cardId}) - res := suite.requestJson(url, reqBody, http.MethodPost) + res := suite.requestJson(url, req, http.MethodPost) // Convert response body from json to map - resBodyAsByteArray, _ := io.ReadAll(res.Body) - resBody := make(map[string]interface{}) - _ = json.Unmarshal(resBodyAsByteArray, &resBody) + resBody := utils.JsonBodyToMap(res) assert.Equal(t, http.StatusInternalServerError, res.StatusCode) assert.Equal(t, "Player not found", resBody["message"]) @@ -140,114 +152,96 @@ func (suite *IntegrationTestSuite) TestTransmitIntelligenceE2E() { suite.T().Run("it can fail when player card not found", func(t *testing.T) { playerId := rand.Intn(playerCount) + 1 - cardId := math.MaxInt32 + cardId := uint(math.MaxInt32) url := strings.ReplaceAll(api, "{player_id}", strconv.Itoa(playerId)) - req := PlayCardRequest{CardId: cardId} - reqBody, _ := json.Marshal(req) + req := utils.RequestToJsonBody(PlayCardRequest{CardID: cardId}) - res := suite.requestJson(url, reqBody, http.MethodPost) + res := suite.requestJson(url, req, http.MethodPost) // Convert response body from json to map - resBodyAsByteArray, _ := io.ReadAll(res.Body) - resBody := make(map[string]interface{}) - _ = json.Unmarshal(resBodyAsByteArray, &resBody) + resBody := utils.JsonBodyToMap(res) assert.Equal(t, http.StatusInternalServerError, res.StatusCode) assert.Equal(t, "Card not found", resBody["message"]) }) suite.T().Run("it can fail when game is end", func(t *testing.T) { - playerId := rand.Intn(playerCount) + 1 - - // Get player's card - cards, _ := suite.playerRepo.GetPlayerWithPlayerCards(context.TODO(), playerId) + id := rand.Intn(playerCount) + player := game.Players[id] // Random card id - num := rand.Intn(len(cards.PlayerCards)) - cardId := cards.PlayerCards[num].CardId + num := rand.Intn(len(player.PlayerCards)) + cardId := player.PlayerCards[num].CardID // Set player to current player - suite.gameServ.UpdateCurrentPlayer(context.TODO(), game, playerId) + game.CurrentPlayerID = player.ID + game.Status = enums.GameEnd + _ = suite.db.Save(&game) - // Set game status to end - suite.gameServ.UpdateStatus(context.TODO(), game, enums.GameEnd) + url := strings.ReplaceAll(api, "{player_id}", strconv.Itoa(int(player.ID))) - url := strings.ReplaceAll(api, "{player_id}", strconv.Itoa(playerId)) - req := PlayCardRequest{CardId: cardId} - reqBody, _ := json.Marshal(req) + req := utils.RequestToJsonBody(PlayCardRequest{CardID: cardId}) - res := suite.requestJson(url, reqBody, http.MethodPost) + res := suite.requestJson(url, req, http.MethodPost) // Convert response body from json to map - resBodyAsByteArray, _ := io.ReadAll(res.Body) - resBody := make(map[string]interface{}) - _ = json.Unmarshal(resBodyAsByteArray, &resBody) + resBody := utils.JsonBodyToMap(res) assert.Equal(t, http.StatusInternalServerError, res.StatusCode) assert.Equal(t, "遊戲已結束", resBody["message"]) // Recover game status to start - suite.gameServ.UpdateStatus(context.TODO(), game, enums.GameStart) + game.Status = enums.GameStart + _ = suite.db.Save(&game) }) suite.T().Run("it can fail when not player's turn", func(t *testing.T) { - playerId := rand.Intn(playerCount) + 1 - - // Get player's card - cards, _ := suite.playerRepo.GetPlayerWithPlayerCards(context.TODO(), playerId) + id := rand.Intn(playerCount) + player := game.Players[id] // Random card id - num := rand.Intn(len(cards.PlayerCards)) - cardId := cards.PlayerCards[num].CardId + num := rand.Intn(len(player.PlayerCards)) + cardId := player.PlayerCards[num].CardID // Set other player to current player - suite.gameServ.UpdateCurrentPlayer(context.TODO(), game, playerId-1) + game.CurrentPlayerID = player.ID + 1 + _ = suite.db.Save(&game) - url := strings.ReplaceAll(api, "{player_id}", strconv.Itoa(playerId)) - req := PlayCardRequest{CardId: cardId} - reqBody, _ := json.Marshal(req) + url := strings.ReplaceAll(api, "{player_id}", strconv.Itoa(int(player.ID))) + req := utils.RequestToJsonBody(PlayCardRequest{CardID: cardId}) - res := suite.requestJson(url, reqBody, http.MethodPost) + res := suite.requestJson(url, req, http.MethodPost) // Convert response body from json to map - resBodyAsByteArray, _ := io.ReadAll(res.Body) - resBody := make(map[string]interface{}) - _ = json.Unmarshal(resBodyAsByteArray, &resBody) + resBody := utils.JsonBodyToMap(res) assert.Equal(t, http.StatusInternalServerError, res.StatusCode) assert.Equal(t, "尚未輪到你出牌", resBody["message"]) }) suite.T().Run("it can success when valid card id", func(t *testing.T) { - playerId := rand.Intn(playerCount) + 1 - - // Get player's card - cards, _ := suite.playerRepo.GetPlayerWithPlayerCards(context.TODO(), playerId) + id := rand.Intn(playerCount) + player := game.Players[id] // Random card id - num := rand.Intn(len(cards.PlayerCards)) - cardId := cards.PlayerCards[num].CardId + num := rand.Intn(len(player.PlayerCards)) + cardId := player.PlayerCards[num].CardID // Set player to current player - suite.gameServ.UpdateCurrentPlayer(context.TODO(), game, playerId) + game.CurrentPlayerID = player.ID + _ = suite.db.Save(&game) - url := strings.ReplaceAll(api, "{player_id}", strconv.Itoa(playerId)) - req := PlayCardRequest{CardId: cardId} - reqBody, _ := json.Marshal(req) + url := strings.ReplaceAll(api, "{player_id}", strconv.Itoa(int(player.ID))) - res := suite.requestJson(url, reqBody, http.MethodPost) + req := utils.RequestToJsonBody(PlayCardRequest{CardID: cardId}) - // Convert response body from json to map - resBodyAsByteArray, _ := io.ReadAll(res.Body) - resBody := make(map[string]interface{}) - _ = json.Unmarshal(resBodyAsByteArray, &resBody) + res := suite.requestJson(url, req, http.MethodPost) assert.Equal(t, http.StatusOK, res.StatusCode) - assert.Equal(t, true, resBody["result"]) }) } type PlayCardRequest struct { - CardId int `json:"card_id"` + CardID uint `json:"card_id"` }