671 lines
18 KiB
Go
671 lines
18 KiB
Go
package users
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"dk/internal/database"
|
|
)
|
|
|
|
func setupTestDB(t *testing.T) *database.DB {
|
|
testDB := "test_users.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 users table
|
|
createTable := `CREATE TABLE users (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
username TEXT NOT NULL,
|
|
password TEXT NOT NULL,
|
|
email TEXT NOT NULL,
|
|
verified INTEGER NOT NULL DEFAULT 0,
|
|
token TEXT NOT NULL DEFAULT '',
|
|
registered INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
last_online INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
auth INTEGER NOT NULL DEFAULT 0,
|
|
x INTEGER NOT NULL DEFAULT 0,
|
|
y INTEGER NOT NULL DEFAULT 0,
|
|
class_id INTEGER NOT NULL DEFAULT 0,
|
|
currently TEXT NOT NULL DEFAULT 'In Town',
|
|
fighting INTEGER NOT NULL DEFAULT 0,
|
|
monster_id INTEGER NOT NULL DEFAULT 0,
|
|
monster_hp INTEGER NOT NULL DEFAULT 0,
|
|
monster_sleep INTEGER NOT NULL DEFAULT 0,
|
|
monster_immune INTEGER NOT NULL DEFAULT 0,
|
|
uber_damage INTEGER NOT NULL DEFAULT 0,
|
|
uber_defense INTEGER NOT NULL DEFAULT 0,
|
|
hp INTEGER NOT NULL DEFAULT 15,
|
|
mp INTEGER NOT NULL DEFAULT 0,
|
|
tp INTEGER NOT NULL DEFAULT 10,
|
|
max_hp INTEGER NOT NULL DEFAULT 15,
|
|
max_mp INTEGER NOT NULL DEFAULT 0,
|
|
max_tp INTEGER NOT NULL DEFAULT 10,
|
|
level INTEGER NOT NULL DEFAULT 1,
|
|
gold INTEGER NOT NULL DEFAULT 100,
|
|
exp INTEGER NOT NULL DEFAULT 0,
|
|
gold_bonus INTEGER NOT NULL DEFAULT 0,
|
|
exp_bonus INTEGER NOT NULL DEFAULT 0,
|
|
strength INTEGER NOT NULL DEFAULT 5,
|
|
dexterity INTEGER NOT NULL DEFAULT 5,
|
|
attack INTEGER NOT NULL DEFAULT 5,
|
|
defense INTEGER NOT NULL DEFAULT 5,
|
|
weapon_id INTEGER NOT NULL DEFAULT 0,
|
|
armor_id INTEGER NOT NULL DEFAULT 0,
|
|
shield_id INTEGER NOT NULL DEFAULT 0,
|
|
slot_1_id INTEGER NOT NULL DEFAULT 0,
|
|
slot_2_id INTEGER NOT NULL DEFAULT 0,
|
|
slot_3_id INTEGER NOT NULL DEFAULT 0,
|
|
weapon_name TEXT NOT NULL DEFAULT '',
|
|
armor_name TEXT NOT NULL DEFAULT '',
|
|
shield_name TEXT NOT NULL DEFAULT '',
|
|
slot_1_name TEXT NOT NULL DEFAULT '',
|
|
slot_2_name TEXT NOT NULL DEFAULT '',
|
|
slot_3_name TEXT NOT NULL DEFAULT '',
|
|
drop_code INTEGER NOT NULL DEFAULT 0,
|
|
spells TEXT NOT NULL DEFAULT '',
|
|
towns TEXT NOT NULL DEFAULT ''
|
|
)`
|
|
|
|
if err := db.Exec(createTable); err != nil {
|
|
t.Fatalf("Failed to create users table: %v", err)
|
|
}
|
|
|
|
// Insert test data with specific timestamps
|
|
now := time.Now().Unix()
|
|
testUsers := `INSERT INTO users (username, password, email, verified, token, registered, last_online, auth,
|
|
x, y, class_id, level, gold, exp, hp, mp, tp, max_hp, max_mp, max_tp,
|
|
strength, dexterity, attack, defense, spells, towns) VALUES
|
|
('alice', 'hashed_pass_1', 'alice@example.com', 1, '', ?, ?, 0, 10, 20, 1, 5, 500, 1250, 25, 15, 12, 25, 15, 12, 8, 7, 10, 8, '1,2,5', '1,2'),
|
|
('bob', 'hashed_pass_2', 'bob@example.com', 1, '', ?, ?, 2, -5, 15, 2, 3, 300, 750, 20, 8, 10, 20, 8, 10, 6, 8, 8, 9, '3,4', '1'),
|
|
('charlie', 'hashed_pass_3', 'charlie@example.com', 0, 'verify_token_123', ?, ?, 4, 0, 0, 3, 1, 100, 0, 15, 0, 10, 15, 0, 10, 5, 5, 5, 5, '', ''),
|
|
('diana', 'hashed_pass_4', 'diana@example.com', 1, '', ?, ?, 0, 25, -10, 1, 8, 1200, 3500, 35, 25, 15, 35, 25, 15, 12, 10, 15, 12, '1,2,3,6,7', '1,2,3,4')`
|
|
|
|
timestamps := []any{
|
|
now - 86400*7, now - 3600*2, // alice: registered 1 week ago, last online 2 hours ago
|
|
now - 86400*5, now - 86400*1, // bob: registered 5 days ago, last online 1 day ago
|
|
now - 86400*1, now - 86400*1, // charlie: registered 1 day ago, last online 1 day ago
|
|
now - 86400*30, now - 3600*1, // diana: registered 1 month ago, last online 1 hour ago
|
|
}
|
|
|
|
if err := db.Exec(testUsers, timestamps...); err != nil {
|
|
t.Fatalf("Failed to insert test users: %v", err)
|
|
}
|
|
|
|
return db
|
|
}
|
|
|
|
func TestFind(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
// Test finding existing user
|
|
user, err := Find(db, 1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to find user: %v", err)
|
|
}
|
|
|
|
if user.ID != 1 {
|
|
t.Errorf("Expected ID 1, got %d", user.ID)
|
|
}
|
|
if user.Username != "alice" {
|
|
t.Errorf("Expected username 'alice', got '%s'", user.Username)
|
|
}
|
|
if user.Email != "alice@example.com" {
|
|
t.Errorf("Expected email 'alice@example.com', got '%s'", user.Email)
|
|
}
|
|
if user.Verified != 1 {
|
|
t.Errorf("Expected verified 1, got %d", user.Verified)
|
|
}
|
|
if user.Auth != 0 {
|
|
t.Errorf("Expected auth 0, got %d", user.Auth)
|
|
}
|
|
if user.Level != 5 {
|
|
t.Errorf("Expected level 5, got %d", user.Level)
|
|
}
|
|
|
|
// Test finding non-existent user
|
|
_, err = Find(db, 999)
|
|
if err == nil {
|
|
t.Error("Expected error when finding non-existent user")
|
|
}
|
|
}
|
|
|
|
func TestAll(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
users, err := All(db)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get all users: %v", err)
|
|
}
|
|
|
|
if len(users) != 4 {
|
|
t.Errorf("Expected 4 users, got %d", len(users))
|
|
}
|
|
|
|
// Check ordering (by registered DESC)
|
|
if len(users) >= 2 {
|
|
if users[0].Registered < users[1].Registered {
|
|
t.Error("Expected users to be ordered by registration date (newest first)")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestByUsername(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
// Test finding existing user by username
|
|
user, err := ByUsername(db, "alice")
|
|
if err != nil {
|
|
t.Fatalf("Failed to find user by username: %v", err)
|
|
}
|
|
|
|
if user.Username != "alice" {
|
|
t.Errorf("Expected username 'alice', got '%s'", user.Username)
|
|
}
|
|
if user.ID != 1 {
|
|
t.Errorf("Expected ID 1, got %d", user.ID)
|
|
}
|
|
|
|
// Test case insensitive search
|
|
userUpper, err := ByUsername(db, "ALICE")
|
|
if err != nil {
|
|
t.Fatalf("Failed to find user by uppercase username: %v", err)
|
|
}
|
|
|
|
if userUpper.ID != user.ID {
|
|
t.Error("Expected case insensitive search to return same user")
|
|
}
|
|
|
|
// Test non-existent user
|
|
_, err = ByUsername(db, "nonexistent")
|
|
if err == nil {
|
|
t.Error("Expected error when finding non-existent user by username")
|
|
}
|
|
}
|
|
|
|
func TestByEmail(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
// Test finding existing user by email
|
|
user, err := ByEmail(db, "bob@example.com")
|
|
if err != nil {
|
|
t.Fatalf("Failed to find user by email: %v", err)
|
|
}
|
|
|
|
if user.Email != "bob@example.com" {
|
|
t.Errorf("Expected email 'bob@example.com', got '%s'", user.Email)
|
|
}
|
|
if user.Username != "bob" {
|
|
t.Errorf("Expected username 'bob', got '%s'", user.Username)
|
|
}
|
|
|
|
// Test non-existent email
|
|
_, err = ByEmail(db, "nonexistent@example.com")
|
|
if err == nil {
|
|
t.Error("Expected error when finding non-existent user by email")
|
|
}
|
|
}
|
|
|
|
func TestByLevel(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
// Test users at level 1
|
|
level1Users, err := ByLevel(db, 1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get users by level: %v", err)
|
|
}
|
|
|
|
expectedCount := 1 // Charlie is level 1
|
|
if len(level1Users) != expectedCount {
|
|
t.Errorf("Expected %d users at level 1, got %d", expectedCount, len(level1Users))
|
|
}
|
|
|
|
// Verify all users are level 1
|
|
for _, user := range level1Users {
|
|
if user.Level != 1 {
|
|
t.Errorf("Expected level 1, got %d for user %s", user.Level, user.Username)
|
|
}
|
|
}
|
|
|
|
// Test level with no users
|
|
noUsers, err := ByLevel(db, 99)
|
|
if err != nil {
|
|
t.Fatalf("Failed to query non-existent level: %v", err)
|
|
}
|
|
|
|
if len(noUsers) != 0 {
|
|
t.Errorf("Expected 0 users at level 99, got %d", len(noUsers))
|
|
}
|
|
}
|
|
|
|
func TestOnline(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
// Test users online within the last 6 hours
|
|
onlineUsers, err := Online(db, 6*time.Hour)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get online users: %v", err)
|
|
}
|
|
|
|
// Alice (2 hours ago) and Diana (1 hour ago) should be included
|
|
expectedCount := 2
|
|
if len(onlineUsers) != expectedCount {
|
|
t.Errorf("Expected %d users online within 6 hours, got %d", expectedCount, len(onlineUsers))
|
|
}
|
|
|
|
// Check ordering (by last_online DESC)
|
|
if len(onlineUsers) >= 2 {
|
|
if onlineUsers[0].LastOnline < onlineUsers[1].LastOnline {
|
|
t.Error("Expected online users to be ordered by last online time")
|
|
}
|
|
}
|
|
|
|
// Test narrow time window
|
|
recentUsers, err := Online(db, 30*time.Minute)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get recently online users: %v", err)
|
|
}
|
|
|
|
// No users should be online within the last 30 minutes
|
|
if len(recentUsers) != 0 {
|
|
t.Errorf("Expected 0 users online within 30 minutes, got %d", len(recentUsers))
|
|
}
|
|
}
|
|
|
|
func TestBuilder(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
// Create new user using builder
|
|
testTime := time.Now()
|
|
user, err := NewBuilder(db).
|
|
WithUsername("testuser").
|
|
WithPassword("hashed_password").
|
|
WithEmail("test@example.com").
|
|
WithVerified(true).
|
|
WithAuth(2).
|
|
WithClassID(2).
|
|
WithPosition(50, -25).
|
|
WithLevel(3).
|
|
WithGold(250).
|
|
WithStats(7, 6, 8, 7).
|
|
WithHP(20, 20).
|
|
WithMP(10, 10).
|
|
WithTP(12, 12).
|
|
WithCurrently("Exploring").
|
|
WithRegisteredTime(testTime).
|
|
WithSpells([]string{"1", "3", "5"}).
|
|
WithTowns([]string{"1", "2"}).
|
|
Create()
|
|
|
|
if err != nil {
|
|
t.Fatalf("Failed to create user with builder: %v", err)
|
|
}
|
|
|
|
if user.ID == 0 {
|
|
t.Error("Expected non-zero ID after creation")
|
|
}
|
|
if user.Username != "testuser" {
|
|
t.Errorf("Expected username 'testuser', got '%s'", user.Username)
|
|
}
|
|
if user.Email != "test@example.com" {
|
|
t.Errorf("Expected email 'test@example.com', got '%s'", user.Email)
|
|
}
|
|
if user.Verified != 1 {
|
|
t.Errorf("Expected verified 1, got %d", user.Verified)
|
|
}
|
|
if user.Auth != 2 {
|
|
t.Errorf("Expected auth 2, got %d", user.Auth)
|
|
}
|
|
if user.ClassID != 2 {
|
|
t.Errorf("Expected class_id 2, got %d", user.ClassID)
|
|
}
|
|
if user.X != 50 || user.Y != -25 {
|
|
t.Errorf("Expected position (50, -25), got (%d, %d)", user.X, user.Y)
|
|
}
|
|
if user.Level != 3 {
|
|
t.Errorf("Expected level 3, got %d", user.Level)
|
|
}
|
|
if user.Gold != 250 {
|
|
t.Errorf("Expected gold 250, got %d", user.Gold)
|
|
}
|
|
if user.Registered != testTime.Unix() {
|
|
t.Errorf("Expected registered time %d, got %d", testTime.Unix(), user.Registered)
|
|
}
|
|
|
|
// Verify it was saved to database
|
|
foundUser, err := Find(db, user.ID)
|
|
if err != nil {
|
|
t.Fatalf("Failed to find created user: %v", err)
|
|
}
|
|
|
|
if foundUser.Username != "testuser" {
|
|
t.Errorf("Created user not found in database")
|
|
}
|
|
|
|
// Test builder with defaults
|
|
defaultUser, err := NewBuilder(db).
|
|
WithUsername("defaultuser").
|
|
WithPassword("password").
|
|
WithEmail("default@example.com").
|
|
Create()
|
|
|
|
if err != nil {
|
|
t.Fatalf("Failed to create user with defaults: %v", err)
|
|
}
|
|
|
|
// Should have default values
|
|
if defaultUser.Level != 1 {
|
|
t.Errorf("Expected default level 1, got %d", defaultUser.Level)
|
|
}
|
|
if defaultUser.Gold != 100 {
|
|
t.Errorf("Expected default gold 100, got %d", defaultUser.Gold)
|
|
}
|
|
if defaultUser.HP != 15 {
|
|
t.Errorf("Expected default HP 15, got %d", defaultUser.HP)
|
|
}
|
|
|
|
// Test convenience methods
|
|
adminUser, err := NewBuilder(db).
|
|
WithUsername("admin").
|
|
WithPassword("admin_pass").
|
|
WithEmail("admin@example.com").
|
|
AsAdmin().
|
|
Create()
|
|
|
|
if err != nil {
|
|
t.Fatalf("Failed to create admin user: %v", err)
|
|
}
|
|
|
|
if adminUser.Auth != 4 {
|
|
t.Errorf("Expected admin auth 4, got %d", adminUser.Auth)
|
|
}
|
|
|
|
moderatorUser, err := NewBuilder(db).
|
|
WithUsername("mod").
|
|
WithPassword("mod_pass").
|
|
WithEmail("mod@example.com").
|
|
AsModerator().
|
|
Create()
|
|
|
|
if err != nil {
|
|
t.Fatalf("Failed to create moderator user: %v", err)
|
|
}
|
|
|
|
if moderatorUser.Auth != 2 {
|
|
t.Errorf("Expected moderator auth 2, got %d", moderatorUser.Auth)
|
|
}
|
|
}
|
|
|
|
func TestSave(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
user, err := Find(db, 1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to find user: %v", err)
|
|
}
|
|
|
|
// Modify user
|
|
user.Username = "alice_updated"
|
|
user.Email = "alice_updated@example.com"
|
|
user.Level = 10
|
|
user.Gold = 1000
|
|
user.UpdateLastOnline()
|
|
|
|
// Save changes
|
|
err = user.Save()
|
|
if err != nil {
|
|
t.Fatalf("Failed to save user: %v", err)
|
|
}
|
|
|
|
// Verify changes were saved
|
|
updatedUser, err := Find(db, 1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to find updated user: %v", err)
|
|
}
|
|
|
|
if updatedUser.Username != "alice_updated" {
|
|
t.Errorf("Expected updated username 'alice_updated', got '%s'", updatedUser.Username)
|
|
}
|
|
if updatedUser.Email != "alice_updated@example.com" {
|
|
t.Errorf("Expected updated email, got '%s'", updatedUser.Email)
|
|
}
|
|
if updatedUser.Level != 10 {
|
|
t.Errorf("Expected updated level 10, got %d", updatedUser.Level)
|
|
}
|
|
if updatedUser.Gold != 1000 {
|
|
t.Errorf("Expected updated gold 1000, got %d", updatedUser.Gold)
|
|
}
|
|
}
|
|
|
|
func TestDelete(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
user, err := Find(db, 1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to find user: %v", err)
|
|
}
|
|
|
|
// Delete user
|
|
err = user.Delete()
|
|
if err != nil {
|
|
t.Fatalf("Failed to delete user: %v", err)
|
|
}
|
|
|
|
// Verify user was deleted
|
|
_, err = Find(db, 1)
|
|
if err == nil {
|
|
t.Error("Expected error when finding deleted user")
|
|
}
|
|
}
|
|
|
|
func TestUserMethods(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
alice, _ := Find(db, 1) // verified, auth 0
|
|
bob, _ := Find(db, 2) // verified, auth 2 (moderator)
|
|
charlie, _ := Find(db, 3) // unverified, auth 4 (admin)
|
|
|
|
// Test time methods
|
|
registeredTime := alice.RegisteredTime()
|
|
if registeredTime.IsZero() {
|
|
t.Error("Expected non-zero registered time")
|
|
}
|
|
|
|
lastOnlineTime := alice.LastOnlineTime()
|
|
if lastOnlineTime.IsZero() {
|
|
t.Error("Expected non-zero last online time")
|
|
}
|
|
|
|
// Test UpdateLastOnline
|
|
originalLastOnline := alice.LastOnline
|
|
alice.UpdateLastOnline()
|
|
if alice.LastOnline <= originalLastOnline {
|
|
t.Error("Expected last online to be updated to current time")
|
|
}
|
|
|
|
// Test verification status
|
|
if !alice.IsVerified() {
|
|
t.Error("Expected alice to be verified")
|
|
}
|
|
if charlie.IsVerified() {
|
|
t.Error("Expected charlie not to be verified")
|
|
}
|
|
|
|
// Test authorization levels
|
|
if alice.IsAdmin() {
|
|
t.Error("Expected alice not to be admin")
|
|
}
|
|
if alice.IsModerator() {
|
|
t.Error("Expected alice not to be moderator")
|
|
}
|
|
if !bob.IsModerator() {
|
|
t.Error("Expected bob to be moderator")
|
|
}
|
|
if !charlie.IsAdmin() {
|
|
t.Error("Expected charlie to be admin")
|
|
}
|
|
|
|
// Test combat status
|
|
if alice.IsFighting() {
|
|
t.Error("Expected alice not to be fighting")
|
|
}
|
|
if !alice.IsAlive() {
|
|
t.Error("Expected alice to be alive")
|
|
}
|
|
|
|
// Test position
|
|
x, y := alice.GetPosition()
|
|
if x != 10 || y != 20 {
|
|
t.Errorf("Expected position (10, 20), got (%d, %d)", x, y)
|
|
}
|
|
|
|
alice.SetPosition(30, 40)
|
|
x, y = alice.GetPosition()
|
|
if x != 30 || y != 40 {
|
|
t.Errorf("Expected updated position (30, 40), got (%d, %d)", x, y)
|
|
}
|
|
}
|
|
|
|
func TestSpellMethods(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
alice, _ := Find(db, 1) // spells: "1,2,5"
|
|
|
|
// Test GetSpellIDs
|
|
spells := alice.GetSpellIDs()
|
|
expectedSpells := []string{"1", "2", "5"}
|
|
if len(spells) != len(expectedSpells) {
|
|
t.Errorf("Expected %d spells, got %d", len(expectedSpells), len(spells))
|
|
}
|
|
|
|
for i, expected := range expectedSpells {
|
|
if i < len(spells) && spells[i] != expected {
|
|
t.Errorf("Expected spell '%s' at position %d, got '%s'", expected, i, spells[i])
|
|
}
|
|
}
|
|
|
|
// Test HasSpell
|
|
if !alice.HasSpell("1") {
|
|
t.Error("Expected alice to have spell '1'")
|
|
}
|
|
if !alice.HasSpell("2") {
|
|
t.Error("Expected alice to have spell '2'")
|
|
}
|
|
if alice.HasSpell("3") {
|
|
t.Error("Expected alice not to have spell '3'")
|
|
}
|
|
|
|
// Test SetSpellIDs
|
|
newSpells := []string{"3", "4", "6", "7"}
|
|
alice.SetSpellIDs(newSpells)
|
|
if alice.Spells != "3,4,6,7" {
|
|
t.Errorf("Expected spells '3,4,6,7', got '%s'", alice.Spells)
|
|
}
|
|
|
|
// Test with empty spells
|
|
charlie, _ := Find(db, 3) // empty spells
|
|
emptySpells := charlie.GetSpellIDs()
|
|
if len(emptySpells) != 0 {
|
|
t.Errorf("Expected 0 spells for empty list, got %d", len(emptySpells))
|
|
}
|
|
}
|
|
|
|
func TestTownMethods(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
alice, _ := Find(db, 1) // towns: "1,2"
|
|
|
|
// Test GetTownIDs
|
|
towns := alice.GetTownIDs()
|
|
expectedTowns := []string{"1", "2"}
|
|
if len(towns) != len(expectedTowns) {
|
|
t.Errorf("Expected %d towns, got %d", len(expectedTowns), len(towns))
|
|
}
|
|
|
|
for i, expected := range expectedTowns {
|
|
if i < len(towns) && towns[i] != expected {
|
|
t.Errorf("Expected town '%s' at position %d, got '%s'", expected, i, towns[i])
|
|
}
|
|
}
|
|
|
|
// Test HasVisitedTown
|
|
if !alice.HasVisitedTown("1") {
|
|
t.Error("Expected alice to have visited town '1'")
|
|
}
|
|
if !alice.HasVisitedTown("2") {
|
|
t.Error("Expected alice to have visited town '2'")
|
|
}
|
|
if alice.HasVisitedTown("3") {
|
|
t.Error("Expected alice not to have visited town '3'")
|
|
}
|
|
|
|
// Test SetTownIDs
|
|
newTowns := []string{"1", "2", "3", "4"}
|
|
alice.SetTownIDs(newTowns)
|
|
if alice.Towns != "1,2,3,4" {
|
|
t.Errorf("Expected towns '1,2,3,4', got '%s'", alice.Towns)
|
|
}
|
|
|
|
// Test with empty towns
|
|
charlie, _ := Find(db, 3) // empty towns
|
|
emptyTowns := charlie.GetTownIDs()
|
|
if len(emptyTowns) != 0 {
|
|
t.Errorf("Expected 0 towns for empty list, got %d", len(emptyTowns))
|
|
}
|
|
}
|
|
|
|
func TestGetEquipmentAndStats(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
defer db.Close()
|
|
|
|
alice, _ := Find(db, 1)
|
|
|
|
// Test GetEquipment
|
|
equipment := alice.GetEquipment()
|
|
if equipment == nil {
|
|
t.Error("Expected non-nil equipment map")
|
|
}
|
|
|
|
weapon, ok := equipment["weapon"].(map[string]any)
|
|
if !ok {
|
|
t.Error("Expected weapon to be a map")
|
|
}
|
|
if weapon["id"].(int) != alice.WeaponID {
|
|
t.Errorf("Expected weapon ID %d, got %v", alice.WeaponID, weapon["id"])
|
|
}
|
|
|
|
// Test GetStats
|
|
stats := alice.GetStats()
|
|
if stats == nil {
|
|
t.Error("Expected non-nil stats map")
|
|
}
|
|
|
|
if stats["level"] != alice.Level {
|
|
t.Errorf("Expected level %d, got %d", alice.Level, stats["level"])
|
|
}
|
|
if stats["hp"] != alice.HP {
|
|
t.Errorf("Expected HP %d, got %d", alice.HP, stats["hp"])
|
|
}
|
|
if stats["strength"] != alice.Strength {
|
|
t.Errorf("Expected strength %d, got %d", alice.Strength, stats["strength"])
|
|
}
|
|
}
|