Files
bamort/backend/character/skills_creation_test.go
T
2025-10-03 21:23:08 +02:00

321 lines
9.1 KiB
Go

package character
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"bamort/database"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
)
// TestGetAllSkillsWithLearningCosts tests the helper function directly
func TestGetAllSkillsWithLearningCosts(t *testing.T) {
// Setup test database
database.SetupTestDB(true, true)
defer database.ResetTestDB()
tests := []struct {
name string
characterClass string
expectError bool
expectSkills bool
}{
{
name: "ValidCharacterClassAs",
characterClass: "As",
expectError: false,
expectSkills: true,
},
{
name: "ValidCharacterClassMagier",
characterClass: "Magier",
expectError: false,
expectSkills: true,
},
{
name: "EmptyCharacterClass",
characterClass: "",
expectError: false,
expectSkills: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
skillsByCategory, err := GetAllSkillsWithLearningCosts(tt.characterClass)
if tt.expectError {
assert.Error(t, err)
return
}
assert.NoError(t, err, "GetAllSkillsWithLearningCosts should not return error")
if tt.expectSkills {
assert.Greater(t, len(skillsByCategory), 0, "Should return at least some skill categories")
// Verify structure of returned data
for categoryName, skills := range skillsByCategory {
assert.NotEmpty(t, categoryName, "Category name should not be empty")
skillsArray := skills
assert.Greater(t, len(skillsArray), 0, "Category should have at least one skill")
// Check first skill structure
if len(skillsArray) > 0 {
skill := skillsArray[0]
assert.Contains(t, skill, "name", "Skill should have name")
assert.Contains(t, skill, "learnCost", "Skill should have learnCost")
name, nameOk := skill["name"].(string)
assert.True(t, nameOk, "Skill name should be string")
assert.NotEmpty(t, name, "Skill name should not be empty")
learnCost, costOk := skill["learnCost"].(int)
assert.True(t, costOk, "Learn cost should be int")
assert.Greater(t, learnCost, 0, "Learn cost should be positive")
assert.LessOrEqual(t, learnCost, 500, "Learn cost should be reasonable")
}
}
t.Logf("Character class %s: Found %d skill categories", tt.characterClass, len(skillsByCategory))
// Log some sample skills for verification
count := 0
for categoryName, skills := range skillsByCategory {
skillsArray := skills
for _, skill := range skillsArray {
skillMap := skill
t.Logf(" %s -> %s: %v LP", categoryName, skillMap["name"], skillMap["learnCost"])
count++
if count >= 5 { // Only log first 5 skills
break
}
}
if count >= 5 {
break
}
}
}
})
}
}
// TestGetAvailableSkillsForCreationHandler tests the HTTP handler directly
func TestHandlerGetAvailableSkillsForCreation(t *testing.T) {
// Setup test database
database.SetupTestDB(true, true)
defer database.ResetTestDB()
tests := []struct {
name string
requestBody interface{}
expectStatus int
expectError bool
validateFunc func(t *testing.T, response map[string]interface{})
}{
{
name: "ValidMagierRequest",
requestBody: gin.H{
"characterClass": "Magier",
},
expectStatus: http.StatusOK,
expectError: false,
validateFunc: func(t *testing.T, response map[string]interface{}) {
assert.Contains(t, response, "skills_by_category")
skillsByCategory := response["skills_by_category"].(map[string]interface{})
assert.Greater(t, len(skillsByCategory), 0, "Should have skill categories")
},
},
{
name: "ValidAsRequest",
requestBody: gin.H{
"characterClass": "As",
},
expectStatus: http.StatusOK,
expectError: false,
validateFunc: func(t *testing.T, response map[string]interface{}) {
assert.Contains(t, response, "skills_by_category")
skillsByCategory := response["skills_by_category"].(map[string]interface{})
assert.Greater(t, len(skillsByCategory), 0, "Should have skill categories")
// Verify that skills have reasonable learning costs
hasReasonableCosts := false
for _, skills := range skillsByCategory {
if skillsList, ok := skills.([]interface{}); ok {
for _, skill := range skillsList {
if skillMap, ok := skill.(map[string]interface{}); ok {
if learnCost, exists := skillMap["leCost"]; exists {
if cost, ok := learnCost.(float64); ok {
assert.Greater(t, cost, 0.0, "Learn cost should be positive")
assert.LessOrEqual(t, cost, 500.0, "Learn cost should be reasonable")
hasReasonableCosts = true
}
}
}
}
}
}
assert.True(t, hasReasonableCosts, "Should find skills with reasonable costs")
},
},
{
name: "EmptyCharacterClass",
requestBody: gin.H{
"characterClass": "",
},
expectStatus: http.StatusBadRequest,
expectError: true,
validateFunc: func(t *testing.T, response map[string]interface{}) {
assert.Contains(t, response, "error")
},
},
{
name: "MissingCharacterClass",
requestBody: gin.H{
"someOtherField": "value",
},
expectStatus: http.StatusBadRequest,
expectError: true,
validateFunc: func(t *testing.T, response map[string]interface{}) {
assert.Contains(t, response, "error")
},
},
{
name: "InvalidJSON",
requestBody: "invalid json string",
expectStatus: http.StatusBadRequest,
expectError: true,
validateFunc: func(t *testing.T, response map[string]interface{}) {
assert.Contains(t, response, "error")
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Prepare request body
var requestBody []byte
var err error
if str, ok := tt.requestBody.(string); ok {
requestBody = []byte(str)
} else {
requestBody, err = json.Marshal(tt.requestBody)
assert.NoError(t, err)
}
// Create HTTP request
req, err := http.NewRequest("POST", "/api/characters/available-skills-creation", bytes.NewBuffer(requestBody))
assert.NoError(t, err)
req.Header.Set("Content-Type", "application/json")
// Create response recorder
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
// Call the handler
GetAvailableSkillsForCreation(c)
// Verify response status
assert.Equal(t, tt.expectStatus, w.Code, "HTTP status should match expected")
// Parse response body
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err, "Response should be valid JSON")
// Run custom validation if provided
if tt.validateFunc != nil {
tt.validateFunc(t, response)
}
// Log response for debugging
if !tt.expectError {
t.Logf("Response for %s: %v", tt.name, response)
}
})
}
}
// BenchmarkGetAllSkillsWithLearningCosts benchmarks the skills loading function
func BenchmarkGetAllSkillsWithLearningCosts(b *testing.B) {
// Setup test database
database.SetupTestDB(true, true)
defer database.ResetTestDB()
characterClass := "Magier"
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := GetAllSkillsWithLearningCosts(characterClass)
if err != nil {
b.Fatalf("GetAllSkillsWithLearningCosts failed: %v", err)
}
}
}
// TestSkillsCreationEndpointIntegration tests the full integration
func TestSkillsCreationEndpointIntegration(t *testing.T) {
// Setup test database
database.SetupTestDB(true, true)
defer database.ResetTestDB()
// Test different character classes
characterClasses := []string{"As", "Magier", "Krieger", "Spitzbube"}
for _, class := range characterClasses {
t.Run("CharacterClass_"+class, func(t *testing.T) {
// Create request
requestData := gin.H{
"characterClass": class,
}
requestBody, err := json.Marshal(requestData)
assert.NoError(t, err)
// Create HTTP request
req, err := http.NewRequest("POST", "/api/characters/available-skills-creation", bytes.NewBuffer(requestBody))
assert.NoError(t, err)
req.Header.Set("Content-Type", "application/json")
// Create response recorder
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
// Call the handler
GetAvailableSkillsForCreation(c)
// Verify response
assert.Equal(t, http.StatusOK, w.Code)
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
// Verify structure
assert.Contains(t, response, "skills_by_category")
skillsByCategory := response["skills_by_category"].(map[string]interface{})
assert.Greater(t, len(skillsByCategory), 0, "Should have at least one skill category")
// Count total skills available
totalSkills := 0
for categoryName, skills := range skillsByCategory {
if skillsList, ok := skills.([]interface{}); ok {
totalSkills += len(skillsList)
t.Logf("Category %s has %d skills", categoryName, len(skillsList))
}
}
assert.Greater(t, totalSkills, 0, "Should have at least some skills available")
t.Logf("Character class %s: %d total skills in %d categories", class, totalSkills, len(skillsByCategory))
})
}
}