042a1d4773
* introduced central package registry by package init function * dynamic registration of routes, model, migrations and initializers. * setting a docker compose project name to prevent shutdown of other containers with the same (composer)name * ai documentation * app template * Create tests for ALL API entpoints in ALL packages Based on current data. Ensure that all API endpoints used in frontend are tested. These tests are crucial for the next refactoring tasks. * adopting agent instructions for a more consistent coding style * added desired module layout and debugging information * Fix All Failing tests All failing tests are fixed now that makes the refactoring more easy since all tests must pass * restored routes for maintenance * added common translations * added new tests for API Endpoint * Merge branch 'separate_business_logic' * added lern and skill improvement cost editing * Set Docker image tag when building to prevent rebuild when nothing has changed * add and remove PP for Weaponskill fixed * add and remove PP for same named skills fixed * add new task
343 lines
13 KiB
Go
343 lines
13 KiB
Go
package importer
|
|
|
|
import (
|
|
"bamort/database"
|
|
"bamort/bmrt/models"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestExportChar2VTT(t *testing.T) {
|
|
database.SetupTestDB()
|
|
defer database.ResetTestDB()
|
|
|
|
// Import a test character first
|
|
fileName := fmt.Sprintf("../../testdata/%s", "VTT_Import1.json")
|
|
char, err := ImportVTTJSON(fileName, 1)
|
|
assert.NoError(t, err, "Expected no error when importing char")
|
|
|
|
// Export the character back to VTT format
|
|
exportedChar, err := ExportCharToVTT(char)
|
|
assert.NoError(t, err, "Expected no error when exporting char")
|
|
|
|
// Basic validations
|
|
assert.Equal(t, char.UserID, uint(1))
|
|
assert.Equal(t, char.Name, exportedChar.Name)
|
|
assert.Equal(t, char.Rasse, exportedChar.Rasse)
|
|
assert.Equal(t, char.Typ, exportedChar.Typ)
|
|
assert.Equal(t, char.Alter, exportedChar.Alter)
|
|
assert.Equal(t, char.Grad, exportedChar.Grad)
|
|
assert.Equal(t, char.Groesse, exportedChar.Groesse)
|
|
assert.Equal(t, char.Gewicht, exportedChar.Gewicht)
|
|
assert.Equal(t, char.Glaube, exportedChar.Glaube)
|
|
assert.Equal(t, char.Hand, exportedChar.Hand)
|
|
|
|
// Check LP
|
|
assert.Equal(t, char.Lp.Max, exportedChar.Lp.Max)
|
|
assert.Equal(t, char.Lp.Value, exportedChar.Lp.Value)
|
|
|
|
// Check AP
|
|
assert.Equal(t, char.Ap.Max, exportedChar.Ap.Max)
|
|
assert.Equal(t, char.Ap.Value, exportedChar.Ap.Value)
|
|
|
|
// Check Eigenschaften
|
|
eigenschaftenMap := getEigenschaftenMap(char)
|
|
assert.Equal(t, eigenschaftenMap["Au"], exportedChar.Eigenschaften.Au)
|
|
assert.Equal(t, eigenschaftenMap["Gs"], exportedChar.Eigenschaften.Gs)
|
|
assert.Equal(t, eigenschaftenMap["Gw"], exportedChar.Eigenschaften.Gw)
|
|
assert.Equal(t, eigenschaftenMap["In"], exportedChar.Eigenschaften.In)
|
|
assert.Equal(t, eigenschaftenMap["Ko"], exportedChar.Eigenschaften.Ko)
|
|
assert.Equal(t, eigenschaftenMap["PA"], exportedChar.Eigenschaften.Pa)
|
|
assert.Equal(t, eigenschaftenMap["St"], exportedChar.Eigenschaften.St)
|
|
assert.Equal(t, eigenschaftenMap["Wk"], exportedChar.Eigenschaften.Wk)
|
|
assert.Equal(t, eigenschaftenMap["Zt"], exportedChar.Eigenschaften.Zt)
|
|
|
|
// Check Fertigkeiten exist
|
|
assert.Greater(t, len(exportedChar.Fertigkeiten), 0, "Should have fertigkeiten")
|
|
|
|
// Check Waffenfertigkeiten exist
|
|
assert.Greater(t, len(exportedChar.Waffenfertigkeiten), 0, "Should have waffenfertigkeiten")
|
|
}
|
|
|
|
func TestExportChar2VTTRoundTrip(t *testing.T) {
|
|
database.SetupTestDB()
|
|
defer database.ResetTestDB()
|
|
|
|
// Import original
|
|
fileName := fmt.Sprintf("../../testdata/%s", "VTT_Import1.json")
|
|
char1, err := ImportVTTJSON(fileName, 1)
|
|
assert.NoError(t, err, "Expected no error when importing char")
|
|
|
|
// Export to VTT
|
|
exportedChar, err := ExportCharToVTT(char1)
|
|
assert.NoError(t, err, "Expected no error when exporting char")
|
|
|
|
// Write to temp file
|
|
tempFile, err := os.CreateTemp("", "vtt_export_*.json")
|
|
assert.NoError(t, err, "Expected no error creating temp file")
|
|
defer os.Remove(tempFile.Name())
|
|
|
|
encoder := json.NewEncoder(tempFile)
|
|
encoder.SetIndent("", " ")
|
|
err = encoder.Encode(exportedChar)
|
|
assert.NoError(t, err, "Expected no error encoding JSON")
|
|
tempFile.Close()
|
|
|
|
// Re-import the exported file
|
|
char2, err := ImportVTTJSON(tempFile.Name(), 6)
|
|
assert.NoError(t, err, "Expected no error when re-importing char")
|
|
|
|
// Compare key fields
|
|
assert.Equal(t, char1.UserID, uint(1), "UserID should match 1 as set in first import")
|
|
assert.Equal(t, char2.UserID, uint(6), "UserID should match 6 as set in re-import")
|
|
assert.Equal(t, char1.Name, char2.Name)
|
|
assert.Equal(t, char1.Rasse, char2.Rasse)
|
|
assert.Equal(t, char1.Typ, char2.Typ)
|
|
assert.Equal(t, char1.Alter, char2.Alter)
|
|
assert.Equal(t, char1.Grad, char2.Grad)
|
|
assert.Equal(t, char1.Lp.Max, char2.Lp.Max)
|
|
assert.Equal(t, char1.Ap.Max, char2.Ap.Max)
|
|
}
|
|
|
|
// Helper function to convert char eigenschaften array to map
|
|
func getEigenschaftenMap(char *models.Char) map[string]int {
|
|
m := make(map[string]int)
|
|
for _, e := range char.Eigenschaften {
|
|
m[e.Name] = e.Value
|
|
}
|
|
return m
|
|
}
|
|
|
|
func TestExportSpellsToCSV(t *testing.T) {
|
|
database.SetupTestDB()
|
|
defer database.ResetTestDB()
|
|
|
|
// Get some spells from master data
|
|
var spells []models.Spell
|
|
database.DB.Limit(10).Find(&spells)
|
|
|
|
if len(spells) == 0 {
|
|
t.Skip("No spells in test database")
|
|
}
|
|
|
|
// Export to CSV
|
|
tempFile, err := os.CreateTemp("", "spell_export_*.csv")
|
|
assert.NoError(t, err, "Expected no error creating temp file")
|
|
defer os.Remove(tempFile.Name())
|
|
tempFile.Close()
|
|
|
|
err = ExportSpellsToCSV(spells, tempFile.Name())
|
|
assert.NoError(t, err, "Expected no error exporting spells to CSV")
|
|
|
|
// Verify file exists and has content
|
|
data, err := os.ReadFile(tempFile.Name())
|
|
assert.NoError(t, err, "Expected no error reading CSV file")
|
|
assert.Greater(t, len(data), 0, "CSV file should have content")
|
|
|
|
// Verify CSV has header
|
|
content := string(data)
|
|
assert.Contains(t, content, "game_system")
|
|
assert.Contains(t, content, "name")
|
|
assert.Contains(t, content, "Beschreibung")
|
|
}
|
|
|
|
func TestExportCharToCSV(t *testing.T) {
|
|
database.SetupTestDB()
|
|
defer database.ResetTestDB()
|
|
|
|
// Import a test character first
|
|
fileName := fmt.Sprintf("../../testdata/%s", "VTT_Import1.json")
|
|
char, err := ImportVTTJSON(fileName, 1)
|
|
assert.NoError(t, err, "Expected no error when importing char")
|
|
|
|
// Export to CSV
|
|
tempFile, err := os.CreateTemp("", "char_export_*.csv")
|
|
assert.NoError(t, err, "Expected no error creating temp file")
|
|
defer os.Remove(tempFile.Name())
|
|
tempFile.Close()
|
|
|
|
err = ExportCharToCSV(char, tempFile.Name())
|
|
assert.NoError(t, err, "Expected no error exporting character to CSV")
|
|
|
|
// Verify file exists and has content
|
|
data, err := os.ReadFile(tempFile.Name())
|
|
assert.NoError(t, err, "Expected no error reading CSV file")
|
|
assert.Greater(t, len(data), 0, "CSV file should have content")
|
|
|
|
// Verify CSV has expected sections
|
|
content := string(data)
|
|
assert.Contains(t, content, char.Name, "Should contain character name")
|
|
assert.Contains(t, content, "Basiseigenschaften", "Should contain base attributes section")
|
|
assert.Contains(t, content, "Fertigkeit", "Should contain skills section")
|
|
assert.Contains(t, content, "Waffe", "Should contain weapons section")
|
|
assert.Contains(t, content, "Erfahrung", "Should contain experience section")
|
|
}
|
|
|
|
func TestExportImportWithoutMasterData(t *testing.T) {
|
|
database.SetupTestDB()
|
|
defer database.ResetTestDB()
|
|
|
|
// Import a test character first
|
|
fileName := fmt.Sprintf("../../testdata/%s", "VTT_Import1.json")
|
|
char1, err := ImportVTTJSON(fileName, 1)
|
|
assert.NoError(t, err, "Expected no error when importing char")
|
|
|
|
// Export to VTT
|
|
vttChar, err := ExportCharToVTT(char1)
|
|
assert.NoError(t, err, "Expected no error when exporting char")
|
|
|
|
// Write to temp file
|
|
tempFile, err := os.CreateTemp("", "vtt_export_*.json")
|
|
assert.NoError(t, err, "Expected no error creating temp file")
|
|
defer os.Remove(tempFile.Name())
|
|
|
|
encoder := json.NewEncoder(tempFile)
|
|
encoder.SetIndent("", " ")
|
|
err = encoder.Encode(vttChar)
|
|
assert.NoError(t, err, "Expected no error encoding JSON")
|
|
tempFile.Close()
|
|
|
|
// Clear all master data tables
|
|
database.DB.Exec("DELETE FROM gsm_skills")
|
|
database.DB.Exec("DELETE FROM gsm_weaponskills")
|
|
database.DB.Exec("DELETE FROM gsm_spells")
|
|
database.DB.Exec("DELETE FROM gsm_weapons")
|
|
database.DB.Exec("DELETE FROM gsm_equipments")
|
|
database.DB.Exec("DELETE FROM gsm_containers")
|
|
database.DB.Exec("DELETE FROM gsm_transportations")
|
|
database.DB.Exec("DELETE FROM gsm_believes")
|
|
database.DB.Exec("DELETE FROM sqlite_sequence WHERE name LIKE 'gsm_%'")
|
|
|
|
// Re-import without master data
|
|
char2, err := ImportVTTJSON(tempFile.Name(), 1)
|
|
assert.NoError(t, err, "Expected no error when re-importing without master data")
|
|
assert.NotNil(t, char2, "Character should be imported")
|
|
|
|
// Verify critical data was preserved
|
|
assert.Equal(t, char1.Name, char2.Name, "Name should match")
|
|
assert.Equal(t, char1.Rasse, char2.Rasse, "Race should match")
|
|
assert.Equal(t, char1.Typ, char2.Typ, "Type should match")
|
|
assert.Equal(t, char1.Grad, char2.Grad, "Grade should match")
|
|
|
|
// Verify LP/AP
|
|
assert.Equal(t, char1.Lp.Max, char2.Lp.Max, "LP Max should match")
|
|
assert.Equal(t, char1.Ap.Max, char2.Ap.Max, "AP Max should match")
|
|
|
|
// Verify skills were imported
|
|
assert.Greater(t, len(char2.Fertigkeiten), 0, "Should have skills after reimport")
|
|
assert.Greater(t, len(char2.Waffenfertigkeiten), 0, "Should have weapon skills after reimport")
|
|
|
|
// Verify weapons were imported
|
|
assert.Greater(t, len(char2.Waffen), 0, "Should have weapons after reimport")
|
|
|
|
// Verify master data was created
|
|
var skillCount, weaponSkillCount, weaponCount int64
|
|
database.DB.Model(&models.Skill{}).Count(&skillCount)
|
|
database.DB.Model(&models.WeaponSkill{}).Count(&weaponSkillCount)
|
|
database.DB.Model(&models.Weapon{}).Count(&weaponCount)
|
|
|
|
assert.Greater(t, skillCount, int64(0), "Master data should be created for skills")
|
|
assert.Greater(t, weaponSkillCount, int64(0), "Master data should be created for weapon skills")
|
|
assert.Greater(t, weaponCount, int64(0), "Master data should be created for weapons")
|
|
}
|
|
|
|
func TestExportImportPreservesCharacterData(t *testing.T) {
|
|
database.SetupTestDB()
|
|
defer database.ResetTestDB()
|
|
|
|
// Import a test character
|
|
fileName := fmt.Sprintf("../../testdata/%s", "VTT_Import1.json")
|
|
char1, err := ImportVTTJSON(fileName, 1)
|
|
assert.NoError(t, err, "Expected no error when importing char")
|
|
|
|
// Store original counts and values
|
|
originalSkillCount := len(char1.Fertigkeiten)
|
|
originalWeaponSkillCount := len(char1.Waffenfertigkeiten)
|
|
originalSpellCount := len(char1.Zauber)
|
|
originalWeaponCount := len(char1.Waffen)
|
|
originalEquipmentCount := len(char1.Ausruestung)
|
|
originalContainerCount := len(char1.Behaeltnisse)
|
|
originalTransportCount := len(char1.Transportmittel)
|
|
|
|
// Export to VTT
|
|
vttChar, err := ExportCharToVTT(char1)
|
|
assert.NoError(t, err, "Expected no error when exporting char")
|
|
|
|
// Verify export has all data
|
|
assert.Equal(t, originalSkillCount, len(vttChar.Fertigkeiten), "All skills should be exported")
|
|
assert.Equal(t, originalWeaponSkillCount, len(vttChar.Waffenfertigkeiten), "All weapon skills should be exported")
|
|
assert.Equal(t, originalSpellCount, len(vttChar.Zauber), "All spells should be exported")
|
|
assert.Equal(t, originalWeaponCount, len(vttChar.Waffen), "All weapons should be exported")
|
|
assert.Equal(t, originalEquipmentCount, len(vttChar.Ausruestung), "All equipment should be exported")
|
|
assert.Equal(t, originalContainerCount, len(vttChar.Behaeltnisse), "All containers should be exported")
|
|
assert.Equal(t, originalTransportCount, len(vttChar.Transportmittel), "All transportation should be exported")
|
|
|
|
// Verify specific skill data is preserved
|
|
if originalSkillCount > 0 {
|
|
assert.NotEmpty(t, vttChar.Fertigkeiten[0].Name, "Skill name should be exported")
|
|
assert.GreaterOrEqual(t, vttChar.Fertigkeiten[0].Fertigkeitswert, 0, "Skill value should be exported")
|
|
}
|
|
|
|
// Verify weapon data is preserved
|
|
if originalWeaponCount > 0 {
|
|
assert.NotEmpty(t, vttChar.Waffen[0].Name, "Weapon name should be exported")
|
|
assert.GreaterOrEqual(t, vttChar.Waffen[0].Gewicht, float64(0), "Weapon weight should be exported")
|
|
}
|
|
|
|
// Write to temp file
|
|
tempFile, err := os.CreateTemp("", "vtt_export_*.json")
|
|
assert.NoError(t, err, "Expected no error creating temp file")
|
|
defer os.Remove(tempFile.Name())
|
|
|
|
encoder := json.NewEncoder(tempFile)
|
|
encoder.SetIndent("", " ")
|
|
err = encoder.Encode(vttChar)
|
|
assert.NoError(t, err, "Expected no error encoding JSON")
|
|
tempFile.Close()
|
|
|
|
// Clear master data
|
|
database.DB.Exec("DELETE FROM gsm_skills")
|
|
database.DB.Exec("DELETE FROM gsm_weaponskills")
|
|
database.DB.Exec("DELETE FROM gsm_spells")
|
|
database.DB.Exec("DELETE FROM gsm_weapons")
|
|
database.DB.Exec("DELETE FROM gsm_equipments")
|
|
database.DB.Exec("DELETE FROM gsm_containers")
|
|
database.DB.Exec("DELETE FROM gsm_transportations")
|
|
|
|
// Re-import
|
|
char2, err := ImportVTTJSON(tempFile.Name(), 1)
|
|
assert.NoError(t, err, "Expected no error when re-importing")
|
|
|
|
// Verify all data was preserved
|
|
assert.Equal(t, originalSkillCount, len(char2.Fertigkeiten), "All skills should be reimported")
|
|
assert.Equal(t, originalWeaponSkillCount, len(char2.Waffenfertigkeiten), "All weapon skills should be reimported")
|
|
assert.Equal(t, originalSpellCount, len(char2.Zauber), "All spells should be reimported")
|
|
assert.Equal(t, originalWeaponCount, len(char2.Waffen), "All weapons should be reimported")
|
|
assert.Equal(t, originalEquipmentCount, len(char2.Ausruestung), "All equipment should be reimported")
|
|
assert.Equal(t, originalContainerCount, len(char2.Behaeltnisse), "All containers should be reimported")
|
|
assert.Equal(t, originalTransportCount, len(char2.Transportmittel), "All transportation should be reimported")
|
|
|
|
// Verify specific values match
|
|
if originalSkillCount > 0 {
|
|
skill1 := findSkillByName(char1.Fertigkeiten, char1.Fertigkeiten[0].Name)
|
|
skill2 := findSkillByName(char2.Fertigkeiten, char1.Fertigkeiten[0].Name)
|
|
assert.NotNil(t, skill1, "Original skill should exist")
|
|
assert.NotNil(t, skill2, "Reimported skill should exist")
|
|
assert.Equal(t, skill1.Fertigkeitswert, skill2.Fertigkeitswert, "Skill values should match")
|
|
}
|
|
}
|
|
|
|
// Helper function to find skill by name
|
|
func findSkillByName(skills []models.SkFertigkeit, name string) *models.SkFertigkeit {
|
|
for i := range skills {
|
|
if skills[i].Name == name {
|
|
return &skills[i]
|
|
}
|
|
}
|
|
return nil
|
|
}
|