package websearch import ( "context" "net/http" "net/http/httptest" "strings" "testing" "img_infinite_canvas/internal/domain/design" ) func TestParseDuckDuckGoResults(t *testing.T) { body := ` Fashion Website Design A fashion ecommerce homepage reference. Hoodie Brand System Brand and hoodie visual language.` results := parseDuckDuckGoResults(body, 5) if len(results) != 2 { t.Fatalf("expected 2 results, got %d", len(results)) } if results[0].Title != "Fashion Website Design" { t.Fatalf("unexpected title: %s", results[0].Title) } if results[0].URL != "https://example.com/fashion" { t.Fatalf("unexpected url: %s", results[0].URL) } if results[0].Snippet != "A fashion ecommerce homepage reference." { t.Fatalf("unexpected snippet: %s", results[0].Snippet) } } func TestBuildVisualSearchQueryForLogoReferencesAvoidsMakerTools(t *testing.T) { query := BuildVisualSearchQuery("Moteva 让设计变简单懂你的设计 Agent,帮我搞定一切设计需求,制作一个 logo") for _, want := range []string{"AI design agent", "logo 设计稿", "设计思路", "brand identity", "-maker", "-generator", "-template"} { if !strings.Contains(query, want) { t.Fatalf("expected query to contain %q, got %q", want, query) } } if strings.Contains(query, "制作一个 logo") { t.Fatalf("expected query to avoid raw prompt wording, got %q", query) } } func TestFetchPageContentExtractsReadableDetails(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html; charset=utf-8") _, _ = w.Write([]byte(` Ignored title

Japanese bakery brand identity

Warm handmade packaging, hand-drawn bread marks, and soft counter signage.

The case study explains reusable color, illustration, and typography choices.

`)) })) defer server.Close() researcher := NewDuckDuckGoResearcher(DuckDuckGoOptions{TimeoutSeconds: 2, MaxPageContentRunes: 220}) content, err := researcher.fetchPageContent(context.Background(), server.URL) if err != nil { t.Fatal(err) } for _, want := range []string{"Japanese bakery brand identity", "Warm handmade packaging", "typography choices"} { if !strings.Contains(content, want) { t.Fatalf("expected page content to contain %q, got %q", want, content) } } for _, unwanted := range []string{"console.log", "Home Pricing Login", "Privacy policy"} { if strings.Contains(content, unwanted) { t.Fatalf("expected page content to omit %q, got %q", unwanted, content) } } } func TestHydrateResultContentsAddsContentForEachResult(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html; charset=utf-8") switch r.URL.Path { case "/one": _, _ = w.Write([]byte(`

First reference

Detailed first page content for the agent.

`)) case "/two": _, _ = w.Write([]byte(`

Second reference

Detailed second page content for the agent.

`)) default: http.NotFound(w, r) } })) defer server.Close() results := []design.ResearchResult{ {Title: "One", URL: server.URL + "/one"}, {Title: "Two", URL: server.URL + "/two"}, } researcher := NewDuckDuckGoResearcher(DuckDuckGoOptions{TimeoutSeconds: 2, MaxPageContentRunes: 200}) researcher.hydrateResultContents(context.Background(), results) if !strings.Contains(results[0].Content, "Detailed first page content") { t.Fatalf("expected first result content, got %#v", results[0]) } if !strings.Contains(results[1].Content, "Detailed second page content") { t.Fatalf("expected second result content, got %#v", results[1]) } }