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 setupCRUDTestEnv(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 TestCreateCharacter(t *testing.T) { setupCRUDTestEnv(t) char := map[string]interface{}{ "name": "Test Krieger", "rasse": "Mensch", "typ": "Kr", "userID": 4, } body, _ := json.Marshal(char) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(4)) c.Request = httptest.NewRequest(http.MethodPost, "/api/characters", bytes.NewBuffer(body)) c.Request.Header.Set("Content-Type", "application/json") CreateCharacter(c) assert.Equal(t, http.StatusCreated, w.Code) var resp models.Char err := json.Unmarshal(w.Body.Bytes(), &resp) assert.NoError(t, err) assert.Equal(t, "Test Krieger", resp.Name) } func TestCreateCharacterInvalidJSON(t *testing.T) { setupCRUDTestEnv(t) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(4)) c.Request = httptest.NewRequest(http.MethodPost, "/api/characters", bytes.NewBufferString("invalid json")) c.Request.Header.Set("Content-Type", "application/json") CreateCharacter(c) assert.Equal(t, http.StatusBadRequest, w.Code) } func TestGetCharacter(t *testing.T) { setupCRUDTestEnv(t) // Create a character to retrieve char := &models.Char{ BamortBase: models.BamortBase{Name: "Fanjo Test"}, UserID: 4, Rasse: "Mensch", Typ: "Kr", } require.NoError(t, database.DB.Create(char).Error) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(4)) c.Params = gin.Params{{Key: "id", Value: fmt.Sprintf("%d", char.ID)}} GetCharacter(c) assert.Equal(t, http.StatusOK, w.Code) var resp models.FeChar err := json.Unmarshal(w.Body.Bytes(), &resp) assert.NoError(t, err) assert.Equal(t, "Fanjo Test", resp.Name) } func TestGetCharacterNotFound(t *testing.T) { setupCRUDTestEnv(t) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(4)) c.Params = gin.Params{{Key: "id", Value: "99999"}} GetCharacter(c) assert.Equal(t, http.StatusInternalServerError, w.Code) } func TestUpdateCharacter(t *testing.T) { setupCRUDTestEnv(t) // Create a character to update char := &models.Char{ BamortBase: models.BamortBase{Name: "Original Name"}, UserID: 4, Rasse: "Mensch", Typ: "Kr", } require.NoError(t, database.DB.Create(char).Error) updateData := map[string]interface{}{ "name": "Updated Name", "rasse": "Elb", "typ": "Kr", "userID": 4, } body, _ := json.Marshal(updateData) 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), bytes.NewBuffer(body)) c.Request.Header.Set("Content-Type", "application/json") UpdateCharacter(c) assert.Equal(t, http.StatusOK, w.Code) } func TestUpdateCharacterNotOwner(t *testing.T) { setupCRUDTestEnv(t) // Create a character owned by user 4 char := &models.Char{ BamortBase: models.BamortBase{Name: "Other User Char"}, UserID: 4, Rasse: "Mensch", Typ: "Kr", } require.NoError(t, database.DB.Create(char).Error) updateData := map[string]interface{}{"name": "Hacked Name"} body, _ := json.Marshal(updateData) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(99)) // Different user 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), bytes.NewBuffer(body)) c.Request.Header.Set("Content-Type", "application/json") UpdateCharacter(c) assert.Equal(t, http.StatusForbidden, w.Code) } func TestDeleteCharacter(t *testing.T) { setupCRUDTestEnv(t) // Create a character to delete char := &models.Char{ BamortBase: models.BamortBase{Name: "To Delete"}, UserID: 4, Rasse: "Mensch", Typ: "Kr", } require.NoError(t, database.DB.Create(char).Error) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(4)) c.Params = gin.Params{{Key: "id", Value: fmt.Sprintf("%d", char.ID)}} DeleteCharacter(c) assert.Equal(t, http.StatusOK, w.Code) assert.Contains(t, w.Body.String(), "deleted successfully") // Verify character is actually deleted var count int64 database.DB.Model(&models.Char{}).Where("id = ?", char.ID).Count(&count) assert.Equal(t, int64(0), count) } func TestDeleteCharacterNotOwner(t *testing.T) { setupCRUDTestEnv(t) char := &models.Char{ BamortBase: models.BamortBase{Name: "Protected"}, UserID: 4, Rasse: "Mensch", Typ: "Kr", } require.NoError(t, database.DB.Create(char).Error) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(99)) c.Params = gin.Params{{Key: "id", Value: fmt.Sprintf("%d", char.ID)}} DeleteCharacter(c) assert.Equal(t, http.StatusForbidden, w.Code) } func TestDeleteCharacterNotFound(t *testing.T) { setupCRUDTestEnv(t) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("userID", uint(4)) c.Params = gin.Params{{Key: "id", Value: "99999"}} DeleteCharacter(c) assert.Equal(t, http.StatusNotFound, w.Code) }