package collections import ( "testing" "eq2emu/internal/database" ) func TestNewMasterList(t *testing.T) { masterList := NewMasterList() if masterList == nil { t.Fatal("NewMasterList returned nil") } if masterList.GetCollectionCount() != 0 { t.Errorf("Expected count 0, got %d", masterList.GetCollectionCount()) } } func TestMasterListBasicOperations(t *testing.T) { db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared") defer db.Close() masterList := NewMasterList() // Create test collections collection1 := NewWithData(1001, "Heritage Collection", "Heritage", 20, db) collection2 := NewWithData(1002, "Treasured Collection", "Treasured", 30, db) // Test adding if !masterList.AddCollection(collection1) { t.Error("Should successfully add collection1") } if !masterList.AddCollection(collection2) { t.Error("Should successfully add collection2") } // Test duplicate add (should fail) if masterList.AddCollection(collection1) { t.Error("Should not add duplicate collection") } if masterList.GetCollectionCount() != 2 { t.Errorf("Expected count 2, got %d", masterList.GetCollectionCount()) } // Test retrieving retrieved := masterList.GetCollection(1001) if retrieved == nil { t.Error("Should retrieve added collection") } if retrieved.GetName() != "Heritage Collection" { t.Errorf("Expected name 'Heritage Collection', got '%s'", retrieved.GetName()) } // Test safe retrieval retrieved, exists := masterList.GetCollectionSafe(1001) if !exists || retrieved == nil { t.Error("GetCollectionSafe should return collection and true") } _, exists = masterList.GetCollectionSafe(9999) if exists { t.Error("GetCollectionSafe should return false for non-existent ID") } // Test HasCollection if !masterList.HasCollection(1001) { t.Error("HasCollection should return true for existing ID") } if masterList.HasCollection(9999) { t.Error("HasCollection should return false for non-existent ID") } // Test removing if !masterList.RemoveCollection(1001) { t.Error("Should successfully remove collection") } if masterList.GetCollectionCount() != 1 { t.Errorf("Expected count 1, got %d", masterList.GetCollectionCount()) } if masterList.HasCollection(1001) { t.Error("Collection should be removed") } // Test clear masterList.ClearCollections() if masterList.GetCollectionCount() != 0 { t.Errorf("Expected count 0 after clear, got %d", masterList.GetCollectionCount()) } } func TestMasterListItemNeeds(t *testing.T) { db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared") defer db.Close() masterList := NewMasterList() // Create collections with items collection1 := NewWithData(1001, "Heritage Collection", "Heritage", 20, db) collection1.CollectionItems = append(collection1.CollectionItems, CollectionItem{ ItemID: 12345, Index: 0, Found: ItemNotFound, }) collection1.CollectionItems = append(collection1.CollectionItems, CollectionItem{ ItemID: 12346, Index: 1, Found: ItemFound, // Already found }) collection2 := NewWithData(1002, "Treasured Collection", "Treasured", 30, db) collection2.CollectionItems = append(collection2.CollectionItems, CollectionItem{ ItemID: 12347, Index: 0, Found: ItemNotFound, }) masterList.AddCollection(collection1) masterList.AddCollection(collection2) // Test NeedsItem if !masterList.NeedsItem(12345) { t.Error("MasterList should need item 12345") } if masterList.NeedsItem(12346) { t.Error("MasterList should not need item 12346 (already found)") } if !masterList.NeedsItem(12347) { t.Error("MasterList should need item 12347") } if masterList.NeedsItem(99999) { t.Error("MasterList should not need item 99999") } // Test GetCollectionsNeedingItem needingItem := masterList.GetCollectionsNeedingItem(12345) if len(needingItem) != 1 { t.Errorf("Expected 1 collection needing item 12345, got %d", len(needingItem)) } needingNone := masterList.GetCollectionsNeedingItem(99999) if len(needingNone) != 0 { t.Errorf("Expected 0 collections needing item 99999, got %d", len(needingNone)) } } func TestMasterListFiltering(t *testing.T) { db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared") defer db.Close() masterList := NewMasterList() // Add test collections collections := []*Collection{ NewWithData(1, "Heritage 1", "Heritage", 10, db), NewWithData(2, "Heritage 2", "Heritage", 20, db), NewWithData(3, "Treasured 1", "Treasured", 15, db), NewWithData(4, "Treasured 2", "Treasured", 25, db), NewWithData(5, "Legendary 1", "Legendary", 30, db), } for _, collection := range collections { masterList.AddCollection(collection) } // Test FindCollectionsByCategory heritageCollections := masterList.FindCollectionsByCategory("Heritage") if len(heritageCollections) != 2 { t.Errorf("FindCollectionsByCategory('Heritage') returned %v results, want 2", len(heritageCollections)) } treasuredCollections := masterList.FindCollectionsByCategory("Treasured") if len(treasuredCollections) != 2 { t.Errorf("FindCollectionsByCategory('Treasured') returned %v results, want 2", len(treasuredCollections)) } // Test FindCollectionsByLevel lowLevel := masterList.FindCollectionsByLevel(10, 15) if len(lowLevel) != 2 { t.Errorf("FindCollectionsByLevel(10, 15) returned %v results, want 2", len(lowLevel)) } midLevel := masterList.FindCollectionsByLevel(20, 25) if len(midLevel) != 2 { t.Errorf("FindCollectionsByLevel(20, 25) returned %v results, want 2", len(midLevel)) } highLevel := masterList.FindCollectionsByLevel(30, 40) if len(highLevel) != 1 { t.Errorf("FindCollectionsByLevel(30, 40) returned %v results, want 1", len(highLevel)) } } func TestMasterListCategories(t *testing.T) { db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared") defer db.Close() masterList := NewMasterList() // Add collections with different categories masterList.AddCollection(NewWithData(1, "Test1", "Heritage", 10, db)) masterList.AddCollection(NewWithData(2, "Test2", "Heritage", 20, db)) masterList.AddCollection(NewWithData(3, "Test3", "Treasured", 15, db)) masterList.AddCollection(NewWithData(4, "Test4", "Legendary", 30, db)) categories := masterList.GetCategories() expectedCategories := []string{"Heritage", "Treasured", "Legendary"} if len(categories) != len(expectedCategories) { t.Errorf("Expected %d categories, got %d", len(expectedCategories), len(categories)) } // Check that all expected categories are present categoryMap := make(map[string]bool) for _, category := range categories { categoryMap[category] = true } for _, expected := range expectedCategories { if !categoryMap[expected] { t.Errorf("Expected category '%s' not found", expected) } } } func TestMasterListGetAll(t *testing.T) { db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared") defer db.Close() masterList := NewMasterList() // Add test collections for i := int32(1); i <= 3; i++ { collection := NewWithData(i*100, "Test", "Heritage", 20, db) masterList.AddCollection(collection) } // Test GetAllCollections (map) allMap := masterList.GetAllCollections() if len(allMap) != 3 { t.Errorf("GetAllCollections() returned %v items, want 3", len(allMap)) } // Verify it's a copy by modifying returned map delete(allMap, 100) if masterList.GetCollectionCount() != 3 { t.Error("Modifying returned map affected internal state") } // Test GetAllCollectionsList (slice) allList := masterList.GetAllCollectionsList() if len(allList) != 3 { t.Errorf("GetAllCollectionsList() returned %v items, want 3", len(allList)) } } func TestMasterListValidation(t *testing.T) { db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared") defer db.Close() masterList := NewMasterList() // Add valid collection collection1 := NewWithData(100, "Valid Collection", "Heritage", 20, db) collection1.CollectionItems = append(collection1.CollectionItems, CollectionItem{ ItemID: 12345, Index: 0, Found: ItemNotFound, }) masterList.AddCollection(collection1) issues := masterList.ValidateCollections() if len(issues) != 0 { t.Errorf("ValidateCollections() returned issues for valid data: %v", issues) } if !masterList.IsValid() { t.Error("IsValid() should return true for valid data") } // Add invalid collection (empty name) collection2 := NewWithData(200, "", "Heritage", 20, db) masterList.AddCollection(collection2) issues = masterList.ValidateCollections() if len(issues) == 0 { t.Error("ValidateCollections() should return issues for invalid data") } if masterList.IsValid() { t.Error("IsValid() should return false for invalid data") } } func TestMasterListStatistics(t *testing.T) { db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared") defer db.Close() masterList := NewMasterList() // Add collections with different categories and levels collection1 := NewWithData(10, "Heritage1", "Heritage", 10, db) collection1.CollectionItems = append(collection1.CollectionItems, CollectionItem{ItemID: 1, Index: 0, Found: 0}) collection1.CollectionItems = append(collection1.CollectionItems, CollectionItem{ItemID: 2, Index: 1, Found: 0}) collection1.RewardItems = append(collection1.RewardItems, CollectionRewardItem{ItemID: 1001, Quantity: 1}) collection2 := NewWithData(20, "Heritage2", "Heritage", 20, db) collection2.CollectionItems = append(collection2.CollectionItems, CollectionItem{ItemID: 3, Index: 0, Found: 0}) collection2.RewardItems = append(collection2.RewardItems, CollectionRewardItem{ItemID: 1002, Quantity: 1}) collection2.SelectableRewardItems = append(collection2.SelectableRewardItems, CollectionRewardItem{ItemID: 1003, Quantity: 1}) collection3 := NewWithData(30, "Treasured1", "Treasured", 30, db) collection3.CollectionItems = append(collection3.CollectionItems, CollectionItem{ItemID: 4, Index: 0, Found: 0}) masterList.AddCollection(collection1) masterList.AddCollection(collection2) masterList.AddCollection(collection3) stats := masterList.GetStatistics() if total, ok := stats["total_collections"].(int); !ok || total != 3 { t.Errorf("total_collections = %v, want 3", stats["total_collections"]) } if totalItems, ok := stats["total_collection_items"].(int); !ok || totalItems != 4 { t.Errorf("total_collection_items = %v, want 4", stats["total_collection_items"]) } if totalRewards, ok := stats["total_rewards"].(int); !ok || totalRewards != 3 { t.Errorf("total_rewards = %v, want 3", stats["total_rewards"]) } if minLevel, ok := stats["min_level"].(int8); !ok || minLevel != 10 { t.Errorf("min_level = %v, want 10", stats["min_level"]) } if maxLevel, ok := stats["max_level"].(int8); !ok || maxLevel != 30 { t.Errorf("max_level = %v, want 30", stats["max_level"]) } if categoryCounts, ok := stats["collections_by_category"].(map[string]int); ok { if categoryCounts["Heritage"] != 2 { t.Errorf("Heritage collections = %v, want 2", categoryCounts["Heritage"]) } if categoryCounts["Treasured"] != 1 { t.Errorf("Treasured collections = %v, want 1", categoryCounts["Treasured"]) } } else { t.Error("collections_by_category not found in statistics") } if avgItems, ok := stats["average_items_per_collection"].(float64); !ok || avgItems != float64(4)/3 { t.Errorf("average_items_per_collection = %v, want %v", avgItems, float64(4)/3) } }