package eprel import ( "context" "encoding/json" "net/http" "net/http/httptest" "strings" "testing" "time" ) func TestNormalizeAndExtractID(t *testing.T) { if got := NormalizeID(" 246834 "); got != "246834" { t.Fatalf("string=%q", got) } if got := NormalizeID(float64(246834)); got != "246834" { t.Fatalf("float=%q", got) } if got := NormalizeID(map[string]any{"#text": "99"}); got != "99" { t.Fatalf("xml text=%q", got) } if IsValidID("") || IsValidID(nil) { t.Fatal("empty should be invalid") } mapped := map[string]any{"title": "Fridge"} raw := map[string]any{"EPRELID": "12345"} if got := ExtractID(mapped, raw); got != "12345" { t.Fatalf("extract=%q", got) } mapped2 := map[string]any{"eprel_id": "777"} if got := ExtractID(mapped2); got != "777" { t.Fatalf("mapped key=%q", got) } attrsOnly := map[string]any{"eprel_id": "888"} if got := ExtractID(nil, nil, attrsOnly); got != "888" { t.Fatalf("attrs extract=%q", got) } if got := ExtractID(map[string]any{"eprel_id": "0000"}); got != "" { t.Fatalf("placeholder must be empty, got %q", got) } if got := NormalizeID("0000"); got != "" { t.Fatalf("NormalizeID placeholder=%q", got) } } func TestClientFetch_httptest(t *testing.T) { mux := http.NewServeMux() mux.HandleFunc("/api/product/246834/fiches", func(w http.ResponseWriter, r *http.Request) { if r.URL.Query().Get("noRedirect") != "true" { t.Errorf("missing noRedirect") } _ = json.NewEncoder(w).Encode(map[string]string{ "address": "/fiches/demo/Fiche_246834_EN.pdf", }) }) mux.HandleFunc("/api/product/246834", func(w http.ResponseWriter, r *http.Request) { if strings.Contains(r.URL.Path, "fiches") || strings.Contains(r.URL.Path, "labels") { http.NotFound(w, r) return } _ = json.NewEncoder(w).Encode(map[string]string{ "energyClass": "A_plus", "energyClassRange": "A-G", }) }) srv := httptest.NewServer(mux) defer srv.Close() client := NewClient(Options{ Enabled: true, BaseURL: srv.URL + "/api", Timeout: 2 * time.Second, HTTPClient: srv.Client(), }) data, err := client.Fetch(context.Background(), "246834") if err != nil { t.Fatal(err) } if data == nil { t.Fatal("expected data") } if !strings.Contains(data.Label, "/product/246834/labels") { t.Fatalf("label=%q", data.Label) } if !strings.HasSuffix(data.PDF, "/fiches/demo/Fiche_246834_EN.pdf") { t.Fatalf("pdf=%q", data.PDF) } if data.EnergyClass != "A-plus" { t.Fatalf("class=%q", data.EnergyClass) } if data.EnergyScale != "A-G" { t.Fatalf("scale=%q", data.EnergyScale) } attrs := MergeInto(nil, data) if attrs[AttrID] != "246834" || attrs[AttrEnergyClass] != "A-plus" { t.Fatalf("attrs=%v", attrs) } if FieldValue(data, "eprel_pdf_url") == "" { t.Fatal("FieldValue pdf empty") } } func TestClientDisabledAndInvalid(t *testing.T) { c := NewClient(Options{Enabled: false}) if c.Enabled() { t.Fatal("should be disabled") } data, err := c.Fetch(context.Background(), "1") if err != nil || data != nil { t.Fatalf("disabled fetch: %v %#v", err, data) } enabled := NewClient(Options{Enabled: true, BaseURL: "http://127.0.0.1:1", Timeout: time.Millisecond}) if _, err := enabled.Fetch(context.Background(), "../etc/passwd"); err == nil { t.Fatal("expected invalid id error") } } func TestClientPartialFicheFailure(t *testing.T) { mux := http.NewServeMux() mux.HandleFunc("/api/product/1/fiches", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "gone", http.StatusNotFound) }) mux.HandleFunc("/api/product/1", func(w http.ResponseWriter, r *http.Request) { _ = json.NewEncoder(w).Encode(map[string]string{"energyClass": "B"}) }) srv := httptest.NewServer(mux) defer srv.Close() client := NewClient(Options{Enabled: true, BaseURL: srv.URL + "/api", Timeout: time.Second, HTTPClient: srv.Client()}) data, err := client.Fetch(context.Background(), "1") if err != nil { t.Fatal(err) } if data.PDF != "" { t.Fatalf("expected empty pdf, got %q", data.PDF) } if data.EnergyClass != "B" { t.Fatalf("class=%q", data.EnergyClass) } if data.Label == "" { t.Fatal("label should still be set") } } func TestAPIKeyNotInErrorBodies(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("X-API-KEY") != "super-secret-key" { t.Errorf("missing api key header") } http.Error(w, "unauthorized secret=super-secret-key", http.StatusUnauthorized) })) defer srv.Close() client := NewClient(Options{ Enabled: true, BaseURL: srv.URL, APIKey: "super-secret-key", Timeout: time.Second, }) // Fiche failure is soft; product info soft-fails too — Fetch still returns label-only data. data, err := client.Fetch(context.Background(), "9") if err != nil { t.Fatal(err) } if data == nil || data.Label == "" { t.Fatal("expected label-only result") } }