408 lines
10 KiB
Go
408 lines
10 KiB
Go
package monsters
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
|
|
"dk/internal/database"
|
|
)
|
|
|
|
func setupTestDB(t *testing.T) *database.DB {
|
|
testDB := "test_monsters.db"
|
|
t.Cleanup(func() {
|
|
os.Remove(testDB)
|
|
})
|
|
|
|
db, err := database.Open(testDB)
|
|
if err != nil {
|
|
t.Fatalf("Failed to open test database: %v", err)
|
|
}
|
|
|
|
// Create monsters table
|
|
createTable := `CREATE TABLE monsters (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL,
|
|
max_hp INTEGER NOT NULL DEFAULT 0,
|
|
max_dmg INTEGER NOT NULL DEFAULT 0,
|
|
armor INTEGER NOT NULL DEFAULT 0,
|
|
level INTEGER NOT NULL DEFAULT 0,
|
|
max_exp INTEGER NOT NULL DEFAULT 0,
|
|
max_gold INTEGER NOT NULL DEFAULT 0,
|
|
immune INTEGER NOT NULL DEFAULT 0
|
|
)`
|
|
|
|
if err := db.Exec(createTable); err != nil {
|
|
t.Fatalf("Failed to create monsters table: %v", err)
|
|
}
|
|
|
|
// Insert test data
|
|
testMonsters := `INSERT INTO monsters (name, max_hp, max_dmg, armor, level, max_exp, max_gold, immune) VALUES
|
|
('Blue Slime', 4, 3, 1, 1, 1, 1, 0),
|
|
('Red Slime', 6, 5, 1, 1, 2, 1, 0),
|
|
('Shadow', 10, 9, 3, 2, 6, 2, 1),
|
|
('Silver Slime', 15, 100, 200, 30, 15, 1000, 2),
|
|
('Raven', 16, 13, 5, 4, 18, 6, 0)`
|
|
|
|
if err := db.Exec(testMonsters); err != nil {
|
|
t.Fatalf("Failed to insert test monsters: %v", err)
|
|
}
|
|
|
|
return db
|
|
}
|
|
|
|
func TestFind(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
// Test finding existing monster
|
|
monster, err := Find(db, 1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to find monster: %v", err)
|
|
}
|
|
|
|
if monster.ID != 1 {
|
|
t.Errorf("Expected ID 1, got %d", monster.ID)
|
|
}
|
|
if monster.Name != "Blue Slime" {
|
|
t.Errorf("Expected name 'Blue Slime', got '%s'", monster.Name)
|
|
}
|
|
if monster.MaxHP != 4 {
|
|
t.Errorf("Expected max_hp 4, got %d", monster.MaxHP)
|
|
}
|
|
if monster.MaxDmg != 3 {
|
|
t.Errorf("Expected max_dmg 3, got %d", monster.MaxDmg)
|
|
}
|
|
if monster.Armor != 1 {
|
|
t.Errorf("Expected armor 1, got %d", monster.Armor)
|
|
}
|
|
if monster.Level != 1 {
|
|
t.Errorf("Expected level 1, got %d", monster.Level)
|
|
}
|
|
if monster.MaxExp != 1 {
|
|
t.Errorf("Expected max_exp 1, got %d", monster.MaxExp)
|
|
}
|
|
if monster.MaxGold != 1 {
|
|
t.Errorf("Expected max_gold 1, got %d", monster.MaxGold)
|
|
}
|
|
if monster.Immune != ImmuneNone {
|
|
t.Errorf("Expected immune %d, got %d", ImmuneNone, monster.Immune)
|
|
}
|
|
|
|
// Test finding non-existent monster
|
|
_, err = Find(db, 999)
|
|
if err == nil {
|
|
t.Error("Expected error when finding non-existent monster")
|
|
}
|
|
}
|
|
|
|
func TestAll(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
monsters, err := All(db)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get all monsters: %v", err)
|
|
}
|
|
|
|
if len(monsters) != 5 {
|
|
t.Errorf("Expected 5 monsters, got %d", len(monsters))
|
|
}
|
|
|
|
// Check first monster (should be ordered by level, then id)
|
|
if monsters[0].Name != "Blue Slime" {
|
|
t.Errorf("Expected first monster to be 'Blue Slime', got '%s'", monsters[0].Name)
|
|
}
|
|
}
|
|
|
|
func TestByLevel(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
// Test level 1 monsters
|
|
level1Monsters, err := ByLevel(db, 1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get level 1 monsters: %v", err)
|
|
}
|
|
|
|
if len(level1Monsters) != 2 {
|
|
t.Errorf("Expected 2 level 1 monsters, got %d", len(level1Monsters))
|
|
}
|
|
|
|
for _, monster := range level1Monsters {
|
|
if monster.Level != 1 {
|
|
t.Errorf("Expected level 1, got %d for monster %s", monster.Level, monster.Name)
|
|
}
|
|
}
|
|
|
|
// Test level that doesn't exist
|
|
noMonsters, err := ByLevel(db, 999)
|
|
if err != nil {
|
|
t.Fatalf("Failed to query non-existent level: %v", err)
|
|
}
|
|
|
|
if len(noMonsters) != 0 {
|
|
t.Errorf("Expected 0 monsters at level 999, got %d", len(noMonsters))
|
|
}
|
|
}
|
|
|
|
func TestByLevelRange(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
// Test level range 1-2
|
|
monsters, err := ByLevelRange(db, 1, 2)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get monsters by level range: %v", err)
|
|
}
|
|
|
|
if len(monsters) != 3 {
|
|
t.Errorf("Expected 3 monsters in level range 1-2, got %d", len(monsters))
|
|
}
|
|
|
|
// Verify all monsters are within range
|
|
for _, monster := range monsters {
|
|
if monster.Level < 1 || monster.Level > 2 {
|
|
t.Errorf("Monster %s level %d is outside range 1-2", monster.Name, monster.Level)
|
|
}
|
|
}
|
|
|
|
// Verify ordering (by level, then id)
|
|
if monsters[0].Level > monsters[len(monsters)-1].Level {
|
|
t.Error("Expected monsters to be ordered by level")
|
|
}
|
|
}
|
|
|
|
func TestByImmunity(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
// Test Hurt immune monsters
|
|
hurtImmune, err := ByImmunity(db, ImmuneHurt)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get Hurt immune monsters: %v", err)
|
|
}
|
|
|
|
if len(hurtImmune) != 1 {
|
|
t.Errorf("Expected 1 Hurt immune monster, got %d", len(hurtImmune))
|
|
}
|
|
|
|
if len(hurtImmune) > 0 && hurtImmune[0].Name != "Shadow" {
|
|
t.Errorf("Expected Hurt immune monster to be 'Shadow', got '%s'", hurtImmune[0].Name)
|
|
}
|
|
|
|
// Test Sleep immune monsters
|
|
sleepImmune, err := ByImmunity(db, ImmuneSleep)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get Sleep immune monsters: %v", err)
|
|
}
|
|
|
|
if len(sleepImmune) != 1 {
|
|
t.Errorf("Expected 1 Sleep immune monster, got %d", len(sleepImmune))
|
|
}
|
|
|
|
// Test no immunity monsters
|
|
noImmunity, err := ByImmunity(db, ImmuneNone)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get non-immune monsters: %v", err)
|
|
}
|
|
|
|
if len(noImmunity) != 3 {
|
|
t.Errorf("Expected 3 non-immune monsters, got %d", len(noImmunity))
|
|
}
|
|
}
|
|
|
|
func TestBuilder(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
// Create new monster using builder
|
|
monster, err := NewBuilder(db).
|
|
WithName("Test Dragon").
|
|
WithMaxHP(100).
|
|
WithMaxDmg(25).
|
|
WithArmor(10).
|
|
WithLevel(15).
|
|
WithMaxExp(500).
|
|
WithMaxGold(100).
|
|
WithImmunity(ImmuneHurt).
|
|
Create()
|
|
|
|
if err != nil {
|
|
t.Fatalf("Failed to create monster with builder: %v", err)
|
|
}
|
|
|
|
if monster.ID == 0 {
|
|
t.Error("Expected non-zero ID after creation")
|
|
}
|
|
if monster.Name != "Test Dragon" {
|
|
t.Errorf("Expected name 'Test Dragon', got '%s'", monster.Name)
|
|
}
|
|
if monster.MaxHP != 100 {
|
|
t.Errorf("Expected max_hp 100, got %d", monster.MaxHP)
|
|
}
|
|
if monster.MaxDmg != 25 {
|
|
t.Errorf("Expected max_dmg 25, got %d", monster.MaxDmg)
|
|
}
|
|
if monster.Armor != 10 {
|
|
t.Errorf("Expected armor 10, got %d", monster.Armor)
|
|
}
|
|
if monster.Level != 15 {
|
|
t.Errorf("Expected level 15, got %d", monster.Level)
|
|
}
|
|
if monster.MaxExp != 500 {
|
|
t.Errorf("Expected max_exp 500, got %d", monster.MaxExp)
|
|
}
|
|
if monster.MaxGold != 100 {
|
|
t.Errorf("Expected max_gold 100, got %d", monster.MaxGold)
|
|
}
|
|
if monster.Immune != ImmuneHurt {
|
|
t.Errorf("Expected immune %d, got %d", ImmuneHurt, monster.Immune)
|
|
}
|
|
|
|
// Verify it was saved to database
|
|
foundMonster, err := Find(db, monster.ID)
|
|
if err != nil {
|
|
t.Fatalf("Failed to find created monster: %v", err)
|
|
}
|
|
|
|
if foundMonster.Name != "Test Dragon" {
|
|
t.Errorf("Created monster not found in database")
|
|
}
|
|
}
|
|
|
|
func TestSave(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
monster, err := Find(db, 1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to find monster: %v", err)
|
|
}
|
|
|
|
// Modify monster
|
|
monster.Name = "Updated Blue Slime"
|
|
monster.MaxHP = 8
|
|
monster.Level = 2
|
|
|
|
// Save changes
|
|
err = monster.Save()
|
|
if err != nil {
|
|
t.Fatalf("Failed to save monster: %v", err)
|
|
}
|
|
|
|
// Verify changes were saved
|
|
updatedMonster, err := Find(db, 1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to find updated monster: %v", err)
|
|
}
|
|
|
|
if updatedMonster.Name != "Updated Blue Slime" {
|
|
t.Errorf("Expected updated name 'Updated Blue Slime', got '%s'", updatedMonster.Name)
|
|
}
|
|
if updatedMonster.MaxHP != 8 {
|
|
t.Errorf("Expected updated max_hp 8, got %d", updatedMonster.MaxHP)
|
|
}
|
|
if updatedMonster.Level != 2 {
|
|
t.Errorf("Expected updated level 2, got %d", updatedMonster.Level)
|
|
}
|
|
}
|
|
|
|
func TestDelete(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
monster, err := Find(db, 1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to find monster: %v", err)
|
|
}
|
|
|
|
// Delete monster
|
|
err = monster.Delete()
|
|
if err != nil {
|
|
t.Fatalf("Failed to delete monster: %v", err)
|
|
}
|
|
|
|
// Verify monster was deleted
|
|
_, err = Find(db, 1)
|
|
if err == nil {
|
|
t.Error("Expected error when finding deleted monster")
|
|
}
|
|
}
|
|
|
|
func TestImmunityMethods(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
blueSlime, _ := Find(db, 1) // No immunity
|
|
shadow, _ := Find(db, 3) // Hurt immune
|
|
silverSlime, _ := Find(db, 4) // Sleep immune
|
|
|
|
// Test IsHurtImmune
|
|
if blueSlime.IsHurtImmune() {
|
|
t.Error("Expected blue slime not to be Hurt immune")
|
|
}
|
|
if !shadow.IsHurtImmune() {
|
|
t.Error("Expected shadow to be Hurt immune")
|
|
}
|
|
if silverSlime.IsHurtImmune() {
|
|
t.Error("Expected silver slime not to be Hurt immune")
|
|
}
|
|
|
|
// Test IsSleepImmune
|
|
if blueSlime.IsSleepImmune() {
|
|
t.Error("Expected blue slime not to be Sleep immune")
|
|
}
|
|
if shadow.IsSleepImmune() {
|
|
t.Error("Expected shadow not to be Sleep immune")
|
|
}
|
|
if !silverSlime.IsSleepImmune() {
|
|
t.Error("Expected silver slime to be Sleep immune")
|
|
}
|
|
|
|
// Test HasImmunity
|
|
if blueSlime.HasImmunity() {
|
|
t.Error("Expected blue slime to have no immunity")
|
|
}
|
|
if !shadow.HasImmunity() {
|
|
t.Error("Expected shadow to have immunity")
|
|
}
|
|
if !silverSlime.HasImmunity() {
|
|
t.Error("Expected silver slime to have immunity")
|
|
}
|
|
|
|
// Test ImmunityName
|
|
if blueSlime.ImmunityName() != "None" {
|
|
t.Errorf("Expected blue slime immunity name 'None', got '%s'", blueSlime.ImmunityName())
|
|
}
|
|
if shadow.ImmunityName() != "Hurt Spells" {
|
|
t.Errorf("Expected shadow immunity name 'Hurt Spells', got '%s'", shadow.ImmunityName())
|
|
}
|
|
if silverSlime.ImmunityName() != "Sleep Spells" {
|
|
t.Errorf("Expected silver slime immunity name 'Sleep Spells', got '%s'", silverSlime.ImmunityName())
|
|
}
|
|
}
|
|
|
|
func TestUtilityMethods(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
blueSlime, _ := Find(db, 1)
|
|
|
|
// Test DifficultyRating
|
|
expectedDifficulty := float64(4+3+1) / float64(1) // (HP + Damage + Armor) / Level
|
|
if blueSlime.DifficultyRating() != expectedDifficulty {
|
|
t.Errorf("Expected difficulty rating %.2f, got %.2f", expectedDifficulty, blueSlime.DifficultyRating())
|
|
}
|
|
|
|
// Test ExpPerHP
|
|
expectedExpPerHP := float64(1) / float64(4) // Exp / HP
|
|
if blueSlime.ExpPerHP() != expectedExpPerHP {
|
|
t.Errorf("Expected exp per HP %.2f, got %.2f", expectedExpPerHP, blueSlime.ExpPerHP())
|
|
}
|
|
|
|
// Test GoldPerHP
|
|
expectedGoldPerHP := float64(1) / float64(4) // Gold / HP
|
|
if blueSlime.GoldPerHP() != expectedGoldPerHP {
|
|
t.Errorf("Expected gold per HP %.2f, got %.2f", expectedGoldPerHP, blueSlime.GoldPerHP())
|
|
}
|
|
} |