package providers import ( "context" "net/http" "net/http/httptest" "strings" "testing" ) // TestOpenLibrarySearchDBFree is the point of the split: a provider is an HTTP // client, so it is exercisable end to end against a stub server with no // database anywhere in sight. func TestOpenLibrarySearchDBFree(t *testing.T) { var gotTitle, gotAuthor, gotLimit, gotUA string srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/search.json" { t.Errorf("path = %q, want /search.json", r.URL.Path) } q := r.URL.Query() gotTitle, gotAuthor, gotLimit = q.Get("title"), q.Get("author"), q.Get("limit") gotUA = r.Header.Get("User-Agent") w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"docs":[ {"key":"/works/OL45804W","title":"The Hobbit","author_name":["J.R.R. Tolkien"], "first_publish_year":1937,"publisher":["Allen & Unwin"],"language":["eng"], "cover_i":8225261,"isbn":["9780261102217"]}, {"key":"/works/OL1W","title":"","author_name":["Nobody"]} ]}`)) })) defer srv.Close() p := NewOpenLibrary() p.BaseURL = srv.URL cands, err := p.Search(context.Background(), Query{Title: "The Hobbit", Author: "Tolkien"}) if err != nil { t.Fatalf("Search: %v", err) } // The untitled doc is dropped rather than surfaced as an empty candidate. if len(cands) != 1 { t.Fatalf("got %d candidates, want 1", len(cands)) } c := cands[0] if c.Provider != "openlibrary" || c.ExternalID != "/works/OL45804W" { t.Errorf("provider id = %s/%s", c.Provider, c.ExternalID) } if c.Title != "The Hobbit" || c.Year != 1937 { t.Errorf("title/year = %q/%d", c.Title, c.Year) } if len(c.Authors) != 1 || c.Authors[0] != "J.R.R. Tolkien" { t.Errorf("Authors = %v", c.Authors) } if c.Publisher != "Allen & Unwin" || c.Language != "eng" { t.Errorf("publisher/language = %q/%q", c.Publisher, c.Language) } if c.ISBN != "9780261102217" { t.Errorf("ISBN = %q", c.ISBN) } if !strings.Contains(c.CoverURL, "covers.openlibrary.org/b/id/8225261") { t.Errorf("CoverURL = %q", c.CoverURL) } if gotTitle != "The Hobbit" || gotAuthor != "Tolkien" { t.Errorf("query title/author = %q/%q", gotTitle, gotAuthor) } if gotLimit != "5" { t.Errorf("limit = %q, want 5", gotLimit) } if gotUA == "" { t.Error("no User-Agent sent; Open Library asks callers to identify themselves") } } func TestOpenLibrarySkipsRequestWithoutATerm(t *testing.T) { p := NewOpenLibrary() cands, err := p.Search(context.Background(), Query{}) if err != nil { t.Fatalf("Search: %v", err) } if len(cands) != 0 { t.Errorf("got %d candidates for an empty query, want 0", len(cands)) } } func TestOpenLibraryReportsHTTPFailure(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusTooManyRequests) })) defer srv.Close() p := NewOpenLibrary() p.BaseURL = srv.URL if _, err := p.Search(context.Background(), Query{Title: "The Hobbit"}); err == nil { t.Fatal("expected an error for a 429 response") } }