package engines import ( "context" "net/http" "strings" "testing" "time" "github.com/ashie/gosearch/internal/contracts" ) func TestBingEngine_EmptyQuery(t *testing.T) { eng := &BingEngine{} resp, err := eng.Search(context.Background(), contracts.SearchRequest{Query: ""}) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(resp.Results) != 0 { t.Errorf("expected 0 results for empty query, got %d", len(resp.Results)) } } func TestBingEngine_Name(t *testing.T) { eng := &BingEngine{} if eng.Name() != "bing" { t.Errorf("expected 'bing', got %q", eng.Name()) } } func TestBingEngine_Uninitialized(t *testing.T) { eng := &BingEngine{} _, err := eng.Search(context.Background(), contracts.SearchRequest{Query: "test"}) if err == nil { t.Error("expected error for uninitialized client") } } func TestBingEngine_LiveRequest(t *testing.T) { if testing.Short() { t.Skip("skipping live request") } client := &http.Client{} eng := &BingEngine{client: client} ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() resp, err := eng.Search(ctx, contracts.SearchRequest{ Query: "golang programming language", }) if err != nil { t.Fatalf("live search failed: %v", err) } // Bing may block non-browser requests gracefully (return 0 results). // The important thing is it doesn't crash. t.Logf("bing returned %d results (total: %d)", len(resp.Results), resp.NumberOfResults) t.Logf("unresponsive: %v", resp.UnresponsiveEngines) if len(resp.UnresponsiveEngines) > 0 { t.Skipf("bing blocked: %v", resp.UnresponsiveEngines[0]) } if len(resp.Results) > 0 { for _, r := range resp.Results { if r.Engine != "bing" { t.Errorf("expected engine 'bing', got %q", r.Engine) } if r.URL == nil || *r.URL == "" { t.Error("expected non-empty URL") } } } } func TestBingEngine_BlockedGracefully(t *testing.T) { // Verify that when Bing returns HTML (bot detection), we get a valid // response with unresponsive_engines instead of an error. html := `Bing requires JavaScript` // This test verifies the structure of the blocked response. resp := contracts.SearchResponse{ Query: "test", NumberOfResults: 0, Results: []contracts.MainResult{}, Answers: []map[string]any{}, Corrections: []string{}, Infoboxes: []map[string]any{}, Suggestions: []string{}, UnresponsiveEngines: [][2]string{{"bing", "blocked by bot detection"}}, } if len(resp.Results) != 0 { t.Error("expected 0 results when blocked") } if len(resp.UnresponsiveEngines) != 1 { t.Error("expected 1 unresponsive engine") } _ = html // just to use the variable _ = strings.TrimSpace // use strings }