package character import ( "bytes" "encoding/json" "fmt" "net/http" "net/http/httptest" "os" "testing" "bamort/database" "bamort/bmrt/models" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func setupExpWealthTestEnv(t *testing.T) { t.Helper() original := os.Getenv("ENVIRONMENT") os.Setenv("ENVIRONMENT", "test") t.Cleanup(func() { if original != "" { os.Setenv("ENVIRONMENT", original) } else { os.Unsetenv("ENVIRONMENT") } }) database.SetupTestDB(true, true) t.Cleanup(database.ResetTestDB) err := models.MigrateStructure() require.NoError(t, err) gin.SetMode(gin.TestMode) } func createTestCharWithEP(t *testing.T, ep int, gold int) *models.Char { t.Helper() char := &models.Char{ BamortBase: models.BamortBase{Name: "Test Char EP"}, UserID: 4, Rasse: "Mensch", Typ: "Kr", } require.NoError(t, database.DB.Create(char).Error) erfahrung := &models.Erfahrungsschatz{ BamortCharTrait: models.BamortCharTrait{ BamortBase: models.BamortBase{}, CharacterID: char.ID, UserID: 4, }, EP: ep, } require.NoError(t, database.DB.Create(erfahrung).Error) vermoegen := &models.Vermoegen{ BamortCharTrait: models.BamortCharTrait{ BamortBase: models.BamortBase{}, CharacterID: char.ID, UserID: 4, }, Goldstuecke: gold, } require.NoError(t, database.DB.Create(vermoegen).Error) return char } func TestGetCharacterExperienceAndWealth(t *testing.T) { setupExpWealthTestEnv(t) char := createTestCharWithEP(t, 500, 100) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(4)) c.Params = gin.Params{{Key: "id", Value: fmt.Sprintf("%d", char.ID)}} GetCharacterExperienceAndWealth(c) assert.Equal(t, http.StatusOK, w.Code) var resp map[string]interface{} require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp)) assert.Equal(t, float64(500), resp["experience_points"]) assert.NotNil(t, resp["wealth"]) } func TestGetCharacterExperienceAndWealthNotFound(t *testing.T) { setupExpWealthTestEnv(t) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(4)) c.Params = gin.Params{{Key: "id", Value: "99999"}} GetCharacterExperienceAndWealth(c) assert.Equal(t, http.StatusNotFound, w.Code) } func TestUpdateCharacterExperience(t *testing.T) { setupExpWealthTestEnv(t) char := createTestCharWithEP(t, 300, 0) reqBody := map[string]interface{}{ "experience_points": 400, } body, _ := json.Marshal(reqBody) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(4)) c.Params = gin.Params{{Key: "id", Value: fmt.Sprintf("%d", char.ID)}} c.Request = httptest.NewRequest(http.MethodPut, "/api/characters/"+fmt.Sprintf("%d", char.ID)+"/experience", bytes.NewBuffer(body)) c.Request.Header.Set("Content-Type", "application/json") UpdateCharacterExperience(c) assert.Equal(t, http.StatusOK, w.Code) var resp map[string]interface{} require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp)) assert.Equal(t, float64(400), resp["experience_points"]) } func TestUpdateCharacterExperienceNotOwner(t *testing.T) { setupExpWealthTestEnv(t) char := createTestCharWithEP(t, 300, 0) reqBody := map[string]interface{}{"experience_points": 100} body, _ := json.Marshal(reqBody) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(99)) c.Params = gin.Params{{Key: "id", Value: fmt.Sprintf("%d", char.ID)}} c.Request = httptest.NewRequest(http.MethodPut, "/", bytes.NewBuffer(body)) c.Request.Header.Set("Content-Type", "application/json") UpdateCharacterExperience(c) assert.Equal(t, http.StatusForbidden, w.Code) } func TestUpdateCharacterExperienceInvalidBody(t *testing.T) { setupExpWealthTestEnv(t) char := createTestCharWithEP(t, 300, 0) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(4)) c.Params = gin.Params{{Key: "id", Value: fmt.Sprintf("%d", char.ID)}} c.Request = httptest.NewRequest(http.MethodPut, "/", bytes.NewBufferString("bad json")) c.Request.Header.Set("Content-Type", "application/json") UpdateCharacterExperience(c) assert.Equal(t, http.StatusBadRequest, w.Code) } func TestUpdateCharacterWealth(t *testing.T) { setupExpWealthTestEnv(t) char := createTestCharWithEP(t, 0, 50) gold := 200 silver := 30 reqBody := map[string]interface{}{ "goldstücke": gold, "silberstücke": silver, } body, _ := json.Marshal(reqBody) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(4)) c.Params = gin.Params{{Key: "id", Value: fmt.Sprintf("%d", char.ID)}} c.Request = httptest.NewRequest(http.MethodPut, "/", bytes.NewBuffer(body)) c.Request.Header.Set("Content-Type", "application/json") UpdateCharacterWealth(c) assert.Equal(t, http.StatusOK, w.Code) var resp map[string]interface{} require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp)) assert.Equal(t, "Wealth updated successfully", resp["message"]) } func TestUpdateCharacterWealthNotOwner(t *testing.T) { setupExpWealthTestEnv(t) char := createTestCharWithEP(t, 0, 50) gold := 999 reqBody := map[string]interface{}{"goldstücke": gold} body, _ := json.Marshal(reqBody) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(99)) c.Params = gin.Params{{Key: "id", Value: fmt.Sprintf("%d", char.ID)}} c.Request = httptest.NewRequest(http.MethodPut, "/", bytes.NewBuffer(body)) c.Request.Header.Set("Content-Type", "application/json") UpdateCharacterWealth(c) assert.Equal(t, http.StatusForbidden, w.Code) } func TestGetCharacterAuditLog(t *testing.T) { setupExpWealthTestEnv(t) char := createTestCharWithEP(t, 100, 0) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(4)) c.Params = gin.Params{{Key: "id", Value: fmt.Sprintf("%d", char.ID)}} c.Request = httptest.NewRequest(http.MethodGet, "/api/characters/"+fmt.Sprintf("%d", char.ID)+"/audit-log", nil) GetCharacterAuditLog(c) assert.Equal(t, http.StatusOK, w.Code) var resp map[string]interface{} require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp)) assert.Equal(t, float64(char.ID), resp["character_id"]) assert.NotNil(t, resp["entries"]) } func TestGetCharacterAuditLogInvalidID(t *testing.T) { setupExpWealthTestEnv(t) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(4)) c.Params = gin.Params{{Key: "id", Value: "notanumber"}} c.Request = httptest.NewRequest(http.MethodGet, "/", nil) GetCharacterAuditLog(c) assert.Equal(t, http.StatusBadRequest, w.Code) } func TestGetAuditLogStats(t *testing.T) { setupExpWealthTestEnv(t) char := createTestCharWithEP(t, 100, 0) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(4)) c.Params = gin.Params{{Key: "id", Value: fmt.Sprintf("%d", char.ID)}} c.Request = httptest.NewRequest(http.MethodGet, "/api/characters/"+fmt.Sprintf("%d", char.ID)+"/audit-log/stats", nil) GetAuditLogStats(c) assert.Equal(t, http.StatusOK, w.Code) var resp map[string]interface{} require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp)) stats, ok := resp["stats"].(map[string]interface{}) require.True(t, ok, "Response should contain 'stats' key") assert.NotNil(t, stats["total_changes"]) assert.NotNil(t, stats["by_field"]) assert.NotNil(t, stats["by_reason"]) }