package handler import ( "strings" "testing" "time" "github.com/prabhupadasays/spsays-bff/internal/model" "github.com/prabhupadasays/spsays-bff/internal/repository" ) // Executes the public /stats template against representative rows and asserts // no submitter email can appear in the output. func TestStatsTemplateHidesEmails(t *testing.T) { now := time.Now() secret := "leak-me@example.com" handle, name := "gopal", "Gopal Das" rows := []model.Feedback{ // anonymous WITH a reply address on file {ID: "1", Category: "bug", Message: "anon with email", CreatedAt: now, HasContactEmail: true, ContactEmail: &secret}, // anonymous with no address at all {ID: "2", Category: "general", Message: "anon no email", CreatedAt: now}, // authed submitter {ID: "3", Category: "feature", Message: "authed", CreatedAt: now, AuthorHandle: &handle, AuthorName: &name, AcknowledgedAt: &now, ResolvedAt: &now}, } var sb strings.Builder err := statsTpl.Execute(&sb, map[string]any{ "Stats": &repository.StatsSnapshot{Users: 1}, "Feedback": rows, "GeneratedAt": "now", }) if err != nil { t.Fatalf("template execute failed: %v", err) } out := sb.String() if strings.Contains(out, secret) || strings.Contains(out, "@example.com") { t.Errorf("submitter email leaked into public /stats output") } for _, want := range []string{"reply address on file", "@gopal", "anon no email"} { if !strings.Contains(out, want) { t.Errorf("expected %q in output", want) } } }