Initial commit of Descrybe v2 without local scratch artifacts.

Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
2026-08-09 22:47:43 +02:00
commit 8580c996c3
1285 changed files with 325780 additions and 0 deletions
+160
View File
@@ -0,0 +1,160 @@
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)
}
}
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")
}
}