feat: Filter und Paginierung für den Werkzeugkatalog, Claude Code als Katalogeintrag
Beide Katalog-Ansichten (Betreiber + Mandant) haben jetzt eine Filterleiste (Freitext über Name/Anbieter/Verarbeitungsländer, Zweck-Dropdown) und serverseitige Paginierung (20/Seite) über ein GET-Formular, kein JavaScript. pagination.go ist generisch gehalten (Go-Generics) für Wiederverwendung in weiteren Listen. Claude Code als eigener Katalogeintrag ergänzt (nicht identisch mit Claude for Work: läuft lokal, hat Dateizugriff, lokale Sitzungs- protokolle mit eigenem Aufbewahrungsrisiko).
This commit is contained in:
@@ -2,10 +2,12 @@ package web_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/netcell-it/deklarix/internal/store"
|
||||
)
|
||||
@@ -116,3 +118,71 @@ func TestBetreiberCannotEditMandantenEigenesWerkzeug(t *testing.T) {
|
||||
t.Fatalf("status = %d, want 404 for a mandanten-eigenes werkzeug", resp.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBetreiberWerkzeugListeFiltertNachSucheUndZweck(t *testing.T) {
|
||||
fs := newFakeStore()
|
||||
s := newServer(t, fs)
|
||||
betreiberCookie := seedAccountWithRole(t, fs, "Deklarix Betreiber", "betreiber@example.com", "betreiber")
|
||||
|
||||
fs.werkzeuge["a"] = store.Werkzeug{
|
||||
ID: "a", Name: "ChatGPT Enterprise", Anbieter: "OpenAI",
|
||||
Verarbeitungslaender: []string{"USA"}, GeeigneteZwecke: []string{"Textgenerierung"},
|
||||
LetztePruefung: time.Now(),
|
||||
}
|
||||
fs.werkzeuge["b"] = store.Werkzeug{
|
||||
ID: "b", Name: "DeepL Pro", Anbieter: "DeepL SE",
|
||||
Verarbeitungslaender: []string{"Deutschland"}, GeeigneteZwecke: []string{"Übersetzung"},
|
||||
LetztePruefung: time.Now(),
|
||||
}
|
||||
|
||||
resp := getWithCookie(t, s, betreiberCookie, "/betreiber/werkzeuge?q=deepl")
|
||||
if resp.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d", resp.Code)
|
||||
}
|
||||
if strings.Contains(resp.Body.String(), "ChatGPT Enterprise") || !strings.Contains(resp.Body.String(), "DeepL Pro") {
|
||||
t.Fatalf("q=deepl sollte nur DeepL Pro zeigen, body: %s", resp.Body.String())
|
||||
}
|
||||
|
||||
resp = getWithCookie(t, s, betreiberCookie, "/betreiber/werkzeuge?zweck=Textgenerierung")
|
||||
if !strings.Contains(resp.Body.String(), "ChatGPT Enterprise") || strings.Contains(resp.Body.String(), "DeepL Pro") {
|
||||
t.Fatalf("zweck=Textgenerierung sollte nur ChatGPT Enterprise zeigen, body: %s", resp.Body.String())
|
||||
}
|
||||
|
||||
resp = getWithCookie(t, s, betreiberCookie, "/betreiber/werkzeuge?q=nichts-passt")
|
||||
if !strings.Contains(resp.Body.String(), "Keine Treffer") {
|
||||
t.Fatalf("erwartet 'Keine Treffer' bei erfolgloser Suche, body: %s", resp.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestBetreiberWerkzeugListePaginiert(t *testing.T) {
|
||||
fs := newFakeStore()
|
||||
s := newServer(t, fs)
|
||||
betreiberCookie := seedAccountWithRole(t, fs, "Deklarix Betreiber", "betreiber@example.com", "betreiber")
|
||||
|
||||
for i := 0; i < 25; i++ {
|
||||
id := fmt.Sprintf("wz-%02d", i)
|
||||
fs.werkzeuge[id] = store.Werkzeug{
|
||||
ID: id, Name: fmt.Sprintf("Werkzeug %02d", i), Anbieter: "Testanbieter",
|
||||
LetztePruefung: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
resp := getWithCookie(t, s, betreiberCookie, "/betreiber/werkzeuge")
|
||||
if resp.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d", resp.Code)
|
||||
}
|
||||
if !strings.Contains(resp.Body.String(), "Seite 1 von 2") {
|
||||
t.Fatalf("erwartet 'Seite 1 von 2' bei 25 Einträgen (20 pro Seite), body: %s", resp.Body.String())
|
||||
}
|
||||
if !strings.Contains(resp.Body.String(), "Weiter") || strings.Contains(resp.Body.String(), "Zurück") {
|
||||
t.Fatalf("Seite 1 sollte einen Weiter-, aber keinen Zurück-Button zeigen")
|
||||
}
|
||||
|
||||
resp = getWithCookie(t, s, betreiberCookie, "/betreiber/werkzeuge?page=2")
|
||||
if !strings.Contains(resp.Body.String(), "Seite 2 von 2") {
|
||||
t.Fatalf("erwartet 'Seite 2 von 2', body: %s", resp.Body.String())
|
||||
}
|
||||
if strings.Contains(resp.Body.String(), "Weiter") || !strings.Contains(resp.Body.String(), "Zurück") {
|
||||
t.Fatalf("Seite 2 sollte einen Zurück-, aber keinen Weiter-Button zeigen")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user