package wiki_test import ( "fmt" "strings" "testing" "github.com/runescape-wiki/rsw/internal/wiki" ) const ( osrsAPIURL = "https://oldschool.runescape.wiki/api.php" rs3APIURL = "https://runescape.wiki/api.php" ) func osrsClient() *wiki.Client { return wiki.NewClient(osrsAPIURL) } func rs3Client() *wiki.Client { return wiki.NewClient(rs3APIURL) } func containsKeyword(t *testing.T, text, keyword string) { t.Helper() if !strings.Contains(strings.ToLower(text), strings.ToLower(keyword)) { t.Errorf("expected to find keyword %q in text, but it was not found.\nText (first 500 chars): %.500s", keyword, text) } } func containsAnyKeyword(t *testing.T, text string, keywords []string) { t.Helper() lower := strings.ToLower(text) for _, kw := range keywords { if strings.Contains(lower, strings.ToLower(kw)) { return } } t.Errorf("expected to find one of %v in text, but none were found.\nText (first 500 chars): %.500s", keywords, text) } // --- OSRS Search Tests --- func TestOSRS_Search_DragonScimitar(t *testing.T) { results, err := osrsClient().Search("dragon scimitar", 5) if err != nil { t.Fatalf("Search failed: %v", err) } if len(results) == 0 { t.Fatal("expected results, got none") } found := false for _, r := range results { if strings.Contains(strings.ToLower(r.Title), "dragon scimitar") { found = true break } } if !found { t.Errorf("expected to find 'Dragon scimitar' in results, got: %v", titlesOf(results)) } } func TestOSRS_Search_AbyssalWhip(t *testing.T) { results, err := osrsClient().Search("abyssal whip", 5) if err != nil { t.Fatalf("Search failed: %v", err) } if len(results) == 0 { t.Fatal("expected results, got none") } found := false for _, r := range results { if strings.Contains(strings.ToLower(r.Title), "abyssal whip") { found = true break } } if !found { t.Errorf("expected to find 'Abyssal whip' in results, got: %v", titlesOf(results)) } } func TestOSRS_Search_MonkeyMadness(t *testing.T) { results, err := osrsClient().Search("Monkey Madness", 5) if err != nil { t.Fatalf("Search failed: %v", err) } if len(results) == 0 { t.Fatal("expected results, got none") } found := false for _, r := range results { if strings.Contains(strings.ToLower(r.Title), "monkey madness") { found = true break } } if !found { t.Errorf("expected to find 'Monkey Madness' in results, got: %v", titlesOf(results)) } } func TestOSRS_Search_MiningTraining(t *testing.T) { results, err := osrsClient().Search("mining training", 5) if err != nil { t.Fatalf("Search failed: %v", err) } if len(results) == 0 { t.Fatal("expected results, got none") } found := false for _, r := range results { lower := strings.ToLower(r.Title) if strings.Contains(lower, "mining") { found = true break } } if !found { t.Errorf("expected to find mining-related result, got: %v", titlesOf(results)) } } func TestOSRS_Search_Snippet_ContainsKeywords(t *testing.T) { results, err := osrsClient().Search("dragon scimitar", 5) if err != nil { t.Fatalf("Search failed: %v", err) } if len(results) == 0 { t.Fatal("expected results, got none") } allText := collectSnippets(results) containsAnyKeyword(t, allText, []string{"dragon", "scimitar", "weapon", "sword"}) } // --- RS3 Search Tests --- func TestRS3_Search_DragonBones(t *testing.T) { results, err := rs3Client().Search("dragon bones", 5) if err != nil { t.Fatalf("Search failed: %v", err) } if len(results) == 0 { t.Fatal("expected results, got none") } found := false for _, r := range results { if strings.Contains(strings.ToLower(r.Title), "dragon bones") { found = true break } } if !found { t.Errorf("expected to find 'Dragon bones' in results, got: %v", titlesOf(results)) } } func TestRS3_Search_PlaguessEnd(t *testing.T) { results, err := rs3Client().Search("Plague's End", 5) if err != nil { t.Fatalf("Search failed: %v", err) } if len(results) == 0 { t.Fatal("expected results, got none") } found := false for _, r := range results { if strings.Contains(strings.ToLower(r.Title), "plague") { found = true break } } if !found { t.Errorf("expected to find plague-related result, got: %v", titlesOf(results)) } } func TestRS3_Search_BluePartyhat(t *testing.T) { results, err := rs3Client().Search("blue partyhat", 5) if err != nil { t.Fatalf("Search failed: %v", err) } if len(results) == 0 { t.Fatal("expected results, got none") } found := false for _, r := range results { lower := strings.ToLower(r.Title) if strings.Contains(lower, "partyhat") || strings.Contains(lower, "party hat") { found = true break } } if !found { t.Errorf("expected to find 'Blue partyhat' in results, got: %v", titlesOf(results)) } } func TestRS3_Search_PrayerTraining(t *testing.T) { results, err := rs3Client().Search("prayer training", 5) if err != nil { t.Fatalf("Search failed: %v", err) } if len(results) == 0 { t.Fatal("expected results, got none") } found := false for _, r := range results { lower := strings.ToLower(r.Title) if strings.Contains(lower, "prayer") { found = true break } } if !found { t.Errorf("expected to find prayer-related result, got: %v", titlesOf(results)) } } // --- OSRS Page Tests --- func TestOSRS_GetPage_DragonScimitar_ContainsKeyInfo(t *testing.T) { page, err := osrsClient().GetPage("Dragon scimitar") if err != nil { t.Fatalf("GetPage failed: %v", err) } if page.Wikitext == "" { t.Fatal("expected non-empty wikitext") } containsKeyword(t, page.Wikitext, "scimitar") containsAnyKeyword(t, page.Wikitext, []string{"members", "Members"}) containsAnyKeyword(t, page.Wikitext, []string{"attack", "Attack", "slash", "Slash"}) } func TestOSRS_GetPage_AbyssalWhip_ContainsKeyInfo(t *testing.T) { page, err := osrsClient().GetPage("Abyssal whip") if err != nil { t.Fatalf("GetPage failed: %v", err) } containsKeyword(t, page.Wikitext, "whip") containsAnyKeyword(t, page.Wikitext, []string{"slayer", "Slayer"}) containsAnyKeyword(t, page.Wikitext, []string{"abyssal", "Abyssal"}) } func TestOSRS_GetPage_HasSections(t *testing.T) { page, err := osrsClient().GetPage("Dragon scimitar") if err != nil { t.Fatalf("GetPage failed: %v", err) } if len(page.Sections) == 0 { t.Error("expected page to have sections") } } func TestOSRS_GetPage_MonkeyMadness_Quest(t *testing.T) { page, err := osrsClient().GetPage("Monkey Madness I") if err != nil { t.Fatalf("GetPage failed: %v", err) } containsKeyword(t, page.Wikitext, "quest") containsAnyKeyword(t, page.Wikitext, []string{"gnome", "Gnome", "monkey", "Monkey"}) containsAnyKeyword(t, page.Wikitext, []string{"requirements", "Requirements"}) } // --- RS3 Page Tests --- func TestRS3_GetPage_DragonBones_ContainsKeyInfo(t *testing.T) { page, err := rs3Client().GetPage("Dragon bones") if err != nil { t.Fatalf("GetPage failed: %v", err) } containsKeyword(t, page.Wikitext, "prayer") containsAnyKeyword(t, page.Wikitext, []string{"dragon", "Dragon"}) containsAnyKeyword(t, page.Wikitext, []string{"bone", "Bone", "bones", "Bones"}) } func TestRS3_GetPage_PlaguessEnd_Quest(t *testing.T) { page, err := rs3Client().GetPage("Plague's End") if err != nil { t.Fatalf("GetPage failed: %v", err) } containsKeyword(t, page.Wikitext, "quest") containsAnyKeyword(t, page.Wikitext, []string{"elf", "Elf", "elven", "Elven"}) containsAnyKeyword(t, page.Wikitext, []string{"requirements", "Requirements"}) } // --- Section Tests --- func TestOSRS_GetPage_Sections_DragonScimitar(t *testing.T) { page, err := osrsClient().GetPage("Dragon scimitar") if err != nil { t.Fatalf("GetPage failed: %v", err) } if len(page.Sections) == 0 { t.Fatal("expected at least one section") } sectionNames := make([]string, len(page.Sections)) for i, s := range page.Sections { sectionNames[i] = strings.ToLower(s.Line) } allSections := strings.Join(sectionNames, " ") containsAnyKeyword(t, allSections, []string{"combat", "stats", "bonuses", "item", "creation", "drop"}) } func TestOSRS_GetPageSection_DragonScimitar_FirstSection(t *testing.T) { page, err := osrsClient().GetPage("Dragon scimitar") if err != nil { t.Fatalf("GetPage failed: %v", err) } idx := findSectionContaining(page.Sections, []string{"combat", "bonuses", "stats", "creation", "special"}) if idx < 0 { if len(page.Sections) == 0 { t.Skip("no sections found") } idx = parseFirstSectionIndex(page.Sections) if idx < 0 { t.Skip("could not parse any section index") } } section, err := osrsClient().GetPageSection("Dragon scimitar", idx) if err != nil { t.Fatalf("GetPageSection failed: %v", err) } if section.Wikitext == "" { t.Error("expected non-empty section wikitext") } } func TestOSRS_GetPage_MiningTraining_Sections(t *testing.T) { page, err := osrsClient().GetPage("Mining training") if err != nil { t.Fatalf("GetPage failed: %v", err) } containsKeyword(t, page.Wikitext, "mining") containsAnyKeyword(t, page.Wikitext, []string{"experience", "xp", "level"}) if len(page.Sections) == 0 { t.Error("expected mining training page to have sections") } } func TestOSRS_GetPageSection_MiningTraining_FirstSection(t *testing.T) { page, err := osrsClient().GetPage("Mining training") if err != nil { t.Fatalf("GetPage failed: %v", err) } idx := parseFirstSectionIndex(page.Sections) if idx < 0 { t.Skip("no sections with valid index found") } section, err := osrsClient().GetPageSection("Mining training", idx) if err != nil { t.Fatalf("GetPageSection failed: %v", err) } if section.Wikitext == "" { t.Error("expected non-empty wikitext for section") } containsAnyKeyword(t, section.Wikitext, []string{"mining", "xp", "experience", "level", "ore"}) } func TestRS3_GetPage_PrayerTraining_Sections(t *testing.T) { page, err := rs3Client().GetPage("Prayer training") if err != nil { t.Fatalf("GetPage failed: %v", err) } containsKeyword(t, page.Wikitext, "prayer") containsAnyKeyword(t, page.Wikitext, []string{"experience", "xp", "level", "bones"}) if len(page.Sections) == 0 { t.Error("expected prayer training page to have sections") } } func TestRS3_GetPageSection_PrayerTraining_BonesSection(t *testing.T) { page, err := rs3Client().GetPage("Prayer training") if err != nil { t.Fatalf("GetPage failed: %v", err) } idx := findSectionContaining(page.Sections, []string{"bones", "altars", "bury", "offering"}) if idx < 0 { t.Skip("no bones/altars section found") } section, err := rs3Client().GetPageSection("Prayer training", idx) if err != nil { t.Fatalf("GetPageSection failed: %v", err) } containsAnyKeyword(t, section.Wikitext, []string{"prayer", "bone", "xp", "experience"}) } func TestRS3_GetPage_Slayer_Sections(t *testing.T) { page, err := rs3Client().GetPage("Slayer") if err != nil { t.Fatalf("GetPage failed: %v", err) } containsKeyword(t, page.Wikitext, "slayer") if len(page.Sections) == 0 { t.Error("expected slayer page to have sections") } } func TestRS3_GetPageSection_Slayer_MastersSection(t *testing.T) { page, err := rs3Client().GetPage("Slayer") if err != nil { t.Fatalf("GetPage failed: %v", err) } idx := findSectionContaining(page.Sections, []string{"master", "masters", "tutor"}) if idx < 0 { t.Skip("no masters section found") } section, err := rs3Client().GetPageSection("Slayer", idx) if err != nil { t.Fatalf("GetPageSection failed: %v", err) } containsAnyKeyword(t, section.Wikitext, []string{"slayer", "master", "task"}) } // --- FindSectionIndex Tests --- func TestFindSectionIndex_Found(t *testing.T) { sections := []wiki.Section{ {Index: "1", Line: "Overview"}, {Index: "2", Line: "Combat styles"}, {Index: "3", Line: "Rewards"}, } idx := wiki.FindSectionIndex(sections, "Combat styles") if idx != 2 { t.Errorf("expected index 2, got %d", idx) } } func TestFindSectionIndex_NotFound(t *testing.T) { sections := []wiki.Section{ {Index: "1", Line: "Overview"}, } idx := wiki.FindSectionIndex(sections, "NonExistent") if idx != -1 { t.Errorf("expected -1, got %d", idx) } } func TestFindSectionIndex_Empty(t *testing.T) { idx := wiki.FindSectionIndex(nil, "anything") if idx != -1 { t.Errorf("expected -1 for nil sections, got %d", idx) } } // --- Helpers --- func titlesOf(results []wiki.SearchResult) []string { titles := make([]string, len(results)) for i, r := range results { titles[i] = r.Title } return titles } func collectSnippets(results []wiki.SearchResult) string { var parts []string for _, r := range results { parts = append(parts, r.Snippet) } return strings.Join(parts, " ") } func findSectionContaining(sections []wiki.Section, keywords []string) int { for _, s := range sections { lower := strings.ToLower(s.Line) for _, kw := range keywords { if strings.Contains(lower, strings.ToLower(kw)) { var idx int if _, err := fmt.Sscanf(s.Index, "%d", &idx); err == nil && idx > 0 { return idx } } } } return -1 } func parseFirstSectionIndex(sections []wiki.Section) int { for _, s := range sections { var idx int if _, err := fmt.Sscanf(s.Index, "%d", &idx); err == nil && idx > 0 { return idx } } return -1 }