package models import ( "bamort/database" "bamort/user" "strconv" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func setupCharacterTestDB(t *testing.T) { database.SetupTestDB() // Migrate structures err := MigrateStructure() require.NoError(t, err, "Failed to migrate database structure") // Clean up any existing test data cleanupCharacterTestData(t) } func cleanupCharacterTestData(t *testing.T) { // Delete all characters to ensure clean state err := database.DB.Exec("DELETE FROM char_chars").Error require.NoError(t, err, "Failed to clean up characters") } func createTestUser() *user.User { return &user.User{ UserID: 1, Username: "testuser", Email: "test@example.com", } } func createTestChar(name string) *Char { return &Char{ BamortBase: BamortBase{ Name: name, }, UserID: 1, Rasse: "Mensch", Typ: "Krieger", Alter: 25, Anrede: "Herr", Grad: 3, Gender: "männlich", SocialClass: "Mittelschicht", Groesse: 180, Gewicht: 75, Herkunft: "Alba", Glaube: "Xan", Hand: "rechts", Public: false, Lp: Lp{ Max: 20, Value: 20, }, Ap: Ap{ Max: 30, Value: 30, }, B: B{ Max: 10, Value: 10, }, Merkmale: Merkmale{ Augenfarbe: "blau", Haarfarbe: "braun", Sonstige: "Narbe am rechten Arm", Breite: "normal", Groesse: "groß", }, Bennies: Bennies{ Gg: 1, Gp: 2, Sg: 0, }, Vermoegen: Vermoegen{ Goldstuecke: 100, Silberstuecke: 50, Kupferstuecke: 25, }, Erfahrungsschatz: Erfahrungsschatz{ ES: 150, EP: 25, }, } } func createTestEigenschaft(charID uint, name string, value int) *Eigenschaft { return &Eigenschaft{ CharacterID: charID, UserID: 1, Name: name, Value: value, } } // ============================================================================= // Tests for Char struct // ============================================================================= func TestChar_TableName(t *testing.T) { char := Char{} expected := "char_chars" actual := char.TableName() assert.Equal(t, expected, actual) } func TestChar_Create_Success(t *testing.T) { setupCharacterTestDB(t) testChar := createTestChar("Test Character") err := testChar.Create() assert.NoError(t, err, "Create should succeed") assert.Greater(t, testChar.ID, uint(0), "ID should be set after create") } func TestChar_Create_WithRelations(t *testing.T) { setupCharacterTestDB(t) testChar := createTestChar("Test Character With Relations") // Add some eigenschaften testChar.Eigenschaften = []Eigenschaft{ {UserID: 1, Name: "St", Value: 15}, {UserID: 1, Name: "Gs", Value: 12}, {UserID: 1, Name: "Ko", Value: 14}, } err := testChar.Create() assert.NoError(t, err, "Create with relations should succeed") assert.Greater(t, testChar.ID, uint(0), "ID should be set after create") assert.Len(t, testChar.Eigenschaften, 3, "All eigenschaften should be created") } func TestChar_First_Success(t *testing.T) { setupCharacterTestDB(t) // Create a test character first testChar := createTestChar("Test Character First") err := testChar.Create() require.NoError(t, err, "Character creation should succeed") // Now try to find it foundChar := &Char{} err = foundChar.First("Test Character First") assert.NoError(t, err, "First should succeed") assert.Equal(t, testChar.ID, foundChar.ID, "Found character should have same ID") assert.Equal(t, testChar.Name, foundChar.Name, "Found character should have same name") assert.Equal(t, testChar.Rasse, foundChar.Rasse, "Found character should have same race") } func TestChar_First_NotFound(t *testing.T) { setupCharacterTestDB(t) foundChar := &Char{} err := foundChar.First("Non-Existent Character") assert.Error(t, err, "First should return error for non-existent character") } func TestChar_FirstID_Success(t *testing.T) { setupCharacterTestDB(t) // Create a test character first testChar := createTestChar("Test Character FirstID") err := testChar.Create() require.NoError(t, err, "Character creation should succeed") // Now try to find it by ID foundChar := &Char{} err = foundChar.FirstID(strconv.Itoa(int(testChar.ID))) assert.NoError(t, err, "FirstID should succeed") assert.Equal(t, testChar.ID, foundChar.ID, "Found character should have same ID") assert.Equal(t, testChar.Name, foundChar.Name, "Found character should have same name") } func TestChar_FirstID_NotFound(t *testing.T) { setupCharacterTestDB(t) foundChar := &Char{} err := foundChar.FirstID("999999") assert.Error(t, err, "FirstID should return error for non-existent ID") } func TestChar_FindByUserID_Success(t *testing.T) { setupCharacterTestDB(t) // Create multiple test characters for the same user testChar1 := createTestChar("Test Character 1") testChar2 := createTestChar("Test Character 2") testChar3 := createTestChar("Test Character 3") testChar3.UserID = 2 // Different user err := testChar1.Create() require.NoError(t, err, "Character 1 creation should succeed") err = testChar2.Create() require.NoError(t, err, "Character 2 creation should succeed") err = testChar3.Create() require.NoError(t, err, "Character 3 creation should succeed") // Find characters for user 1 foundChar := &Char{} chars, err := foundChar.FindByUserID(1) assert.NoError(t, err, "FindByUserID should succeed") assert.GreaterOrEqual(t, len(chars), 2, "Should find at least 2 characters for user 1") // Verify all returned characters belong to user 1 for _, char := range chars { assert.Equal(t, uint(1), char.UserID, "All characters should belong to user 1") } } func TestChar_FindByUserID_NoCharacters(t *testing.T) { setupCharacterTestDB(t) foundChar := &Char{} chars, err := foundChar.FindByUserID(999999) assert.NoError(t, err, "FindByUserID should succeed even with no results") assert.Empty(t, chars, "Should return empty slice for user with no characters") } func TestChar_Delete_Success(t *testing.T) { setupCharacterTestDB(t) // Create a test character first testChar := createTestChar("Test Character Delete") err := testChar.Create() require.NoError(t, err, "Character creation should succeed") originalID := testChar.ID // Delete the character err = testChar.Delete() assert.NoError(t, err, "Delete should succeed") // Verify the character is deleted foundChar := &Char{} err = foundChar.FirstID(strconv.Itoa(int(originalID))) assert.Error(t, err, "Character should not be found after deletion") } func TestFindPublicCharList_Success(t *testing.T) { setupCharacterTestDB(t) // Create some test characters testChar1 := createTestChar("Public Character 1") testChar1.Public = true testChar2 := createTestChar("Private Character") testChar2.Public = false testChar3 := createTestChar("Public Character 2") testChar3.Public = true err := testChar1.Create() require.NoError(t, err, "Character 1 creation should succeed") err = testChar2.Create() require.NoError(t, err, "Character 2 creation should succeed") err = testChar3.Create() require.NoError(t, err, "Character 3 creation should succeed") // Find public characters publicChars, err := FindPublicCharList() assert.NoError(t, err, "FindPublicCharList should succeed") assert.GreaterOrEqual(t, len(publicChars), 2, "Should find at least 2 public characters") // Verify all returned characters are public for _, char := range publicChars { assert.True(t, char.Public, "All characters should be public") } } func TestFindCharListByUserID_Success(t *testing.T) { setupCharacterTestDB(t) // Create test characters for different users testChar1 := createTestChar("User 1 Character 1") testChar1.UserID = 1 testChar2 := createTestChar("User 1 Character 2") testChar2.UserID = 1 testChar3 := createTestChar("User 2 Character") testChar3.UserID = 2 err := testChar1.Create() require.NoError(t, err, "Character 1 creation should succeed") err = testChar2.Create() require.NoError(t, err, "Character 2 creation should succeed") err = testChar3.Create() require.NoError(t, err, "Character 3 creation should succeed") // Find characters for user 1 userChars, err := FindCharListByUserID(1) assert.NoError(t, err, "FindCharListByUserID should succeed") assert.GreaterOrEqual(t, len(userChars), 2, "Should find at least 2 characters for user 1") // Verify all returned characters belong to user 1 for _, char := range userChars { assert.Equal(t, uint(1), char.UserID, "All characters should belong to user 1") } } // ============================================================================= // Tests for Eigenschaft struct // ============================================================================= func TestEigenschaft_TableName(t *testing.T) { eigenschaft := Eigenschaft{} expected := "char_eigenschaften" actual := eigenschaft.TableName() assert.Equal(t, expected, actual) } // ============================================================================= // Tests for Lp struct // ============================================================================= func TestLp_TableName(t *testing.T) { lp := Lp{} expected := "char_health" actual := lp.TableName() assert.Equal(t, expected, actual) } // ============================================================================= // Tests for Ap struct // ============================================================================= func TestAp_TableName(t *testing.T) { ap := Ap{} expected := "char_endurances" actual := ap.TableName() assert.Equal(t, expected, actual) } // ============================================================================= // Tests for B struct // ============================================================================= func TestB_TableName(t *testing.T) { b := B{} expected := "char_motionranges" actual := b.TableName() assert.Equal(t, expected, actual) } // ============================================================================= // Tests for Merkmale struct // ============================================================================= func TestMerkmale_TableName(t *testing.T) { merkmale := Merkmale{} expected := "char_characteristics" actual := merkmale.TableName() assert.Equal(t, expected, actual) } // ============================================================================= // Tests for Erfahrungsschatz struct // ============================================================================= func TestErfahrungsschatz_TableName(t *testing.T) { erfahrung := Erfahrungsschatz{} expected := "char_experiances" actual := erfahrung.TableName() assert.Equal(t, expected, actual) } // ============================================================================= // Tests for Bennies struct // ============================================================================= func TestBennies_TableName(t *testing.T) { bennies := Bennies{} expected := "char_bennies" actual := bennies.TableName() assert.Equal(t, expected, actual) } // ============================================================================= // Tests for Vermoegen struct // ============================================================================= func TestVermoegen_TableName(t *testing.T) { vermoegen := Vermoegen{} expected := "char_wealth" actual := vermoegen.TableName() assert.Equal(t, expected, actual) } // ============================================================================= // Integration tests for character with related data // ============================================================================= func TestChar_CreateWithCompleteData(t *testing.T) { setupCharacterTestDB(t) testChar := createTestChar("Complete Character") // Add eigenschaften testChar.Eigenschaften = []Eigenschaft{ {UserID: 1, Name: "St", Value: 15}, {UserID: 1, Name: "Gs", Value: 12}, {UserID: 1, Name: "Ko", Value: 14}, {UserID: 1, Name: "In", Value: 13}, {UserID: 1, Name: "Zt", Value: 11}, } err := testChar.Create() assert.NoError(t, err, "Complete character creation should succeed") assert.Greater(t, testChar.ID, uint(0), "ID should be set after create") // Verify the character can be found with all relations foundChar := &Char{} err = foundChar.First(testChar.Name) require.NoError(t, err, "Character should be found") assert.Equal(t, testChar.Name, foundChar.Name) assert.Equal(t, testChar.Rasse, foundChar.Rasse) assert.Equal(t, testChar.Typ, foundChar.Typ) assert.Equal(t, testChar.Lp.Max, foundChar.Lp.Max) assert.Equal(t, testChar.Ap.Max, foundChar.Ap.Max) assert.Equal(t, testChar.B.Max, foundChar.B.Max) assert.Equal(t, testChar.Merkmale.Augenfarbe, foundChar.Merkmale.Augenfarbe) assert.Equal(t, testChar.Bennies.Gg, foundChar.Bennies.Gg) assert.Equal(t, testChar.Vermoegen.Goldstuecke, foundChar.Vermoegen.Goldstuecke) assert.Equal(t, testChar.Erfahrungsschatz.ES, foundChar.Erfahrungsschatz.ES) } func TestChar_CharacterProgression(t *testing.T) { setupCharacterTestDB(t) // Create a low-level character testChar := createTestChar("Progression Character") testChar.Grad = 1 testChar.Erfahrungsschatz.ES = 50 testChar.Erfahrungsschatz.EP = 0 err := testChar.Create() require.NoError(t, err, "Character creation should succeed") // Simulate character progression testChar.Grad = 2 testChar.Erfahrungsschatz.ES = 100 testChar.Erfahrungsschatz.EP = 25 // Note: We would need an Update method to test this properly // For now, we just verify the data structure can hold progression data assert.Equal(t, 2, testChar.Grad, "Grade should be updated") assert.Equal(t, 100, testChar.Erfahrungsschatz.ES, "Experience should be updated") assert.Equal(t, 25, testChar.Erfahrungsschatz.EP, "Experience points should be updated") } func TestChar_WealthManagement(t *testing.T) { setupCharacterTestDB(t) testChar := createTestChar("Wealthy Character") testChar.Vermoegen.Goldstuecke = 1000 testChar.Vermoegen.Silberstuecke = 500 testChar.Vermoegen.Kupferstuecke = 100 err := testChar.Create() require.NoError(t, err, "Character creation should succeed") // Verify wealth data foundChar := &Char{} err = foundChar.First(testChar.Name) require.NoError(t, err, "Character should be found") assert.Equal(t, 1000, foundChar.Vermoegen.Goldstuecke, "Gold should match") assert.Equal(t, 500, foundChar.Vermoegen.Silberstuecke, "Silver should match") assert.Equal(t, 100, foundChar.Vermoegen.Kupferstuecke, "Copper should match") } func TestChar_EdgeCases(t *testing.T) { setupCharacterTestDB(t) // Test character with minimal data minimalChar := &Char{ BamortBase: BamortBase{ Name: "Minimal Character", }, UserID: 1, Rasse: "Unbekannt", Typ: "Abenteurer", } err := minimalChar.Create() assert.NoError(t, err, "Minimal character should be created successfully") // Test character with extreme values extremeChar := createTestChar("Extreme Character") extremeChar.Alter = 999 extremeChar.Groesse = 300 extremeChar.Gewicht = 500 extremeChar.Lp.Max = 999 extremeChar.Ap.Max = 999 extremeChar.B.Max = 999 err = extremeChar.Create() assert.NoError(t, err, "Character with extreme values should be created successfully") // Test character with special characters in name specialChar := createTestChar("Ä Special Çharacter ñ") err = specialChar.Create() assert.NoError(t, err, "Character with special characters should be created successfully") }