package web_test import ( "context" "net/http" "net/url" "strings" "testing" "github.com/netcell-it/deklarix/internal/store" "github.com/netcell-it/deklarix/internal/web" ) // genehmigeFall reicht einen Antrag ein und genehmigt ihn mit einem // echten, zulässigen Werkzeug — Vorbereitung für Register-Tests, die // einen tatsächlichen Registereintrag brauchen. func genehmigeFall(t *testing.T, fs *fakeStore, s *web.Server) (accountID string) { t.Helper() acc, err := fs.CreateAccount(context.Background(), store.AccountInput{Name: "Register-Mandant"}) if err != nil { t.Fatalf("CreateAccount: %v", err) } fs.werkzeuge["werkzeug-ok"] = store.Werkzeug{ID: "werkzeug-ok", Name: "ChatGPT Enterprise", AVVVerfuegbar: true, TrainingStandard: true} mitarbeiterCookie := seedUserInAccount(t, fs, acc.ID, "mitarbeiter@example.com", "mitarbeiter") createResp := postForm(t, s, mitarbeiterCookie, "/antraege", fullAntragForm()) if createResp.Code != http.StatusSeeOther { t.Fatalf("Antrag anlegen: status = %d, body: %s", createResp.Code, createResp.Body.String()) } var antragID string for id := range fs.antraege { if fs.antraege[id].AccountID == acc.ID { antragID = id } } verantwortlicherCookie := seedUserInAccount(t, fs, acc.ID, "verantwortlicher@example.com", "verantwortlicher") entscheidenResp := postForm(t, s, verantwortlicherCookie, "/faelle/"+antragID+"/entscheiden", url.Values{ "entscheidung": {"genehmigt"}, "werkzeug_id": {"werkzeug-ok"}, }) if entscheidenResp.Code != http.StatusSeeOther { t.Fatalf("Entscheiden: status = %d, body: %s", entscheidenResp.Code, entscheidenResp.Body.String()) } return acc.ID } func TestGenehmigungErzeugtRegistereintrag(t *testing.T) { fs := newFakeStore() s := newServer(t, fs) accountID := genehmigeFall(t, fs, s) list := fs.registereintraege[accountID] if len(list) != 1 { t.Fatalf("registereintraege = %+v, want exactly one entry", list) } e := list[0] if e.Werkzeug != "ChatGPT Enterprise" || e.Zweck != "Angebotstexte generieren" || e.Datenklasse != "personenbezogen" { t.Errorf("Registereintrag = %+v, unerwartete Werte", e) } if e.Verantwortlicher != "verantwortlicher@example.com" { t.Errorf("Verantwortlicher = %q, want verantwortlicher@example.com", e.Verantwortlicher) } } func TestAbgelehnteEntscheidungErzeugtKeinenRegistereintrag(t *testing.T) { fs := newFakeStore() s := newServer(t, fs) antragID, verantwortlicherCookie := seedFallImAccount(t, fs, s, "verantwortlicher") resp := postForm(t, s, verantwortlicherCookie, "/faelle/"+antragID+"/entscheiden", url.Values{ "entscheidung": {"abgelehnt"}, "begruendung": {"Kein Werkzeug verfügbar"}, }) if resp.Code != http.StatusSeeOther { t.Fatalf("status = %d, body: %s", resp.Code, resp.Body.String()) } for _, list := range fs.registereintraege { if len(list) != 0 { t.Fatalf("expected no registereintrag for an abgelehnt Entscheidung, got %+v", list) } } } func TestRegisterListeZeigtGenehmigung(t *testing.T) { fs := newFakeStore() s := newServer(t, fs) accountID := genehmigeFall(t, fs, s) verantwortlicherCookie := seedUserInAccount(t, fs, accountID, "reviewer@example.com", "pruefer") resp := getWithCookie(t, s, verantwortlicherCookie, "/registereintraege") if resp.Code != http.StatusOK { t.Fatalf("status = %d, body: %s", resp.Code, resp.Body.String()) } if !strings.Contains(resp.Body.String(), "ChatGPT Enterprise") { t.Errorf("expected the genehmigtes werkzeug in the register, got: %s", resp.Body.String()) } } func TestRegisterExportCSVEnthaeltEintrag(t *testing.T) { fs := newFakeStore() s := newServer(t, fs) accountID := genehmigeFall(t, fs, s) verantwortlicherCookie := seedUserInAccount(t, fs, accountID, "reviewer@example.com", "pruefer") resp := getWithCookie(t, s, verantwortlicherCookie, "/registereintraege/export.csv") if resp.Code != http.StatusOK { t.Fatalf("status = %d, body: %s", resp.Code, resp.Body.String()) } if ct := resp.Header().Get("Content-Type"); !strings.Contains(ct, "text/csv") { t.Errorf("Content-Type = %q, want text/csv", ct) } if !strings.Contains(resp.Body.String(), "ChatGPT Enterprise") { t.Errorf("expected the werkzeug in the CSV export, got: %s", resp.Body.String()) } } func TestRegisterExportPDFReturnsPDF(t *testing.T) { fs := newFakeStore() s := newServer(t, fs) accountID := genehmigeFall(t, fs, s) verantwortlicherCookie := seedUserInAccount(t, fs, accountID, "reviewer@example.com", "pruefer") resp := getWithCookie(t, s, verantwortlicherCookie, "/registereintraege/export.pdf") if resp.Code != http.StatusOK { t.Fatalf("status = %d, body: %s", resp.Code, resp.Body.String()) } if ct := resp.Header().Get("Content-Type"); ct != "application/pdf" { t.Errorf("Content-Type = %q, want application/pdf", ct) } if !strings.HasPrefix(resp.Body.String(), "%PDF") { t.Error("expected the response body to start with the PDF magic bytes") } } func TestMitarbeiterCannotAccessRegister(t *testing.T) { fs := newFakeStore() s := newServer(t, fs) cookie := seedAccountWithRole(t, fs, "Test-Mandant", "mitarbeiter@example.com", "mitarbeiter") resp := getWithCookie(t, s, cookie, "/registereintraege") if resp.Code != http.StatusNotFound { t.Fatalf("status = %d, want 404 for role mitarbeiter on /registereintraege", resp.Code) } }