Files
glpi-ai-agent/internal/glpi/client_test.go
T
jbergner 523e597e7a
release-tag / release-image (push) Has been cancelled
RC-2
2026-07-28 20:15:43 +02:00

150 lines
5.1 KiB
Go

package glpi
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"
)
func TestOAuthAndGetTicket(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api.php/token":
json.NewEncoder(w).Encode(map[string]any{"access_token": "x", "expires_in": 3600})
case "/api.php/v2.3/Assistance/Ticket/5":
json.NewEncoder(w).Encode(map[string]any{"id": 5, "name": "Hello", "category": map[string]any{"id": 2}, "status": map[string]any{"id": 1}})
default:
http.NotFound(w, r)
}
}))
defer srv.Close()
c := New(srv.URL, "v2.3", "cid", "sec", "u", "p", time.Second)
got, err := c.GetTicket(context.Background(), 5)
if err != nil {
t.Fatal(err)
}
if got.ID != 5 || got.CategoryID != 2 {
t.Fatalf("unexpected %+v", got)
}
}
func TestValidateContractAcceptsVersionPrefixedOpenAPIPaths(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api.php/token":
_ = json.NewEncoder(w).Encode(map[string]any{"access_token": "x", "expires_in": 3600})
case "/api.php/doc.json":
_ = json.NewEncoder(w).Encode(map[string]any{"paths": map[string]any{
"/v2.3/Assistance/Ticket": map[string]any{"get": map[string]any{}},
"/v2.3/Assistance/Ticket/{id}": map[string]any{"get": map[string]any{}, "patch": map[string]any{}},
"/v2.3/Assistance/Ticket/{id}/Timeline/Followup": map[string]any{"get": map[string]any{}, "post": map[string]any{}},
"/v2.3/Dropdowns/ITILCategory": map[string]any{"get": map[string]any{}},
}})
default:
http.NotFound(w, r)
}
}))
defer srv.Close()
c := New(srv.URL, "v2.3", "cid", "sec", "u", "p", time.Second)
if err := c.ValidateContract(context.Background()); err != nil {
t.Fatal(err)
}
}
func TestDiscoverAndListKnowledgeBase(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api.php/token":
_ = json.NewEncoder(w).Encode(map[string]any{"access_token": "x", "expires_in": 3600})
case "/api.php/doc.json":
_ = json.NewEncoder(w).Encode(map[string]any{"paths": map[string]any{
"/v2.3/Knowledge/KnowbaseItem": map[string]any{"get": map[string]any{}},
}})
case "/api.php/v2.3/Knowledge/KnowbaseItem":
_ = json.NewEncoder(w).Encode([]map[string]any{{
"id": 7, "name": "Konto gesperrt", "answer": "<p>Konto entsperren</p>", "date_mod": "2026-07-27 10:00:00",
"categories": []any{map[string]any{"id": 4}},
}})
default:
http.NotFound(w, r)
}
}))
defer srv.Close()
c := New(srv.URL, "v2.3", "cid", "sec", "u", "p", time.Second)
path, err := c.DiscoverKnowledgeBasePath(context.Background(), "auto")
if err != nil {
t.Fatal(err)
}
if path != "/Knowledge/KnowbaseItem" {
t.Fatalf("path=%q", path)
}
items, err := c.ListKnowledgeBaseItems(context.Background(), path, 50, "")
if err != nil {
t.Fatal(err)
}
if len(items) != 1 || items[0].ID != 7 || len(items[0].CategoryIDs) != 1 || items[0].CategoryIDs[0] != 4 {
t.Fatalf("unexpected items: %+v", items)
}
}
func TestAddFollowupPreservesRichHTML(t *testing.T) {
var gotContent string
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api.php/token":
_ = json.NewEncoder(w).Encode(map[string]any{"access_token": "x", "expires_in": 3600})
case "/api.php/v2.3/Assistance/Ticket/5/Timeline/Followup":
var body map[string]any
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
t.Fatal(err)
}
gotContent, _ = body["content"].(string)
w.WriteHeader(http.StatusCreated)
_, _ = w.Write([]byte(`{}`))
default:
http.NotFound(w, r)
}
}))
defer srv.Close()
c := New(srv.URL, "v2.3", "cid", "sec", "u", "p", time.Second)
rich := `<p><strong>Fett</strong></p><ul><li>Eintrag</li></ul><p><a href="https://example.invalid">Link</a></p>`
if err := c.AddFollowup(context.Background(), 5, rich, true); err != nil {
t.Fatal(err)
}
if gotContent != rich {
t.Fatalf("rich HTML changed:\nwant %s\n got %s", rich, gotContent)
}
}
func TestAddFollowupEscapesPlainText(t *testing.T) {
var gotContent string
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api.php/token":
_ = json.NewEncoder(w).Encode(map[string]any{"access_token": "x", "expires_in": 3600})
case "/api.php/v2.3/Assistance/Ticket/5/Timeline/Followup":
var body map[string]any
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
t.Fatal(err)
}
gotContent, _ = body["content"].(string)
w.WriteHeader(http.StatusCreated)
_, _ = w.Write([]byte(`{}`))
default:
http.NotFound(w, r)
}
}))
defer srv.Close()
c := New(srv.URL, "v2.3", "cid", "sec", "u", "p", time.Second)
if err := c.AddFollowup(context.Background(), 5, "Hallo <b>nicht HTML</b>\nZeile 2", false); err != nil {
t.Fatal(err)
}
want := "<p>Hallo &lt;b&gt;nicht HTML&lt;/b&gt;<br>Zeile 2</p>"
if gotContent != want {
t.Fatalf("plain content not escaped:\nwant %s\n got %s", want, gotContent)
}
}