131 lines
4.2 KiB
Go
131 lines
4.2 KiB
Go
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
//go:build linux || freebsd
|
|
|
|
package contactform
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestValidateContact_Happy(t *testing.T) {
|
|
r := &Request{
|
|
Name: "Jane Doe",
|
|
Email: "jane@example.com",
|
|
Service: "architecture",
|
|
Message: "Hello, I would like to discuss a project.",
|
|
}
|
|
if errs := Validate(r, "contact"); len(errs) > 0 {
|
|
t.Fatalf("expected no errors, got %v", errs)
|
|
}
|
|
}
|
|
|
|
func TestValidateContact_DefaultType(t *testing.T) {
|
|
// Unknown / empty type falls back to contact validation.
|
|
r := &Request{Name: "Jane Doe", Email: "jane@example.com", Message: "Hello there."}
|
|
if errs := Validate(r, ""); len(errs) > 0 {
|
|
t.Fatalf("expected no errors with empty type, got %v", errs)
|
|
}
|
|
}
|
|
|
|
func TestValidateContact_RejectsInvalidEmail(t *testing.T) {
|
|
r := &Request{Name: "Jane", Email: "not-an-email", Message: "A message long enough."}
|
|
errs := Validate(r, "contact")
|
|
if len(errs) == 0 {
|
|
t.Fatal("expected error for invalid email")
|
|
}
|
|
if errs[0].Field != "email" {
|
|
t.Errorf("expected field=email, got %q", errs[0].Field)
|
|
}
|
|
}
|
|
|
|
func TestValidateContact_RejectsBadService(t *testing.T) {
|
|
r := &Request{Name: "Jane", Email: "jane@example.com", Service: "hairstyling", Message: "A message long enough."}
|
|
errs := Validate(r, "contact")
|
|
if len(errs) == 0 || errs[0].Field != "service" {
|
|
t.Fatalf("expected service error, got %v", errs)
|
|
}
|
|
}
|
|
|
|
func TestValidateFeedback_OmitsService(t *testing.T) {
|
|
// Feedback validates like generic: name, email, message; no service field.
|
|
r := &Request{Name: "Jane", Email: "jane@example.com", Message: "A message long enough."}
|
|
if errs := Validate(r, "feedback"); len(errs) > 0 {
|
|
t.Fatalf("expected no errors, got %v", errs)
|
|
}
|
|
}
|
|
|
|
func TestValidateGeneric_RejectsShortMessage(t *testing.T) {
|
|
r := &Request{Name: "Jane", Email: "jane@example.com", Message: "short"}
|
|
errs := Validate(r, "generic")
|
|
if len(errs) == 0 || errs[0].Field != "message" {
|
|
t.Fatalf("expected message error, got %v", errs)
|
|
}
|
|
}
|
|
|
|
func TestValidateNewsletter_Happy(t *testing.T) {
|
|
r := &Request{Email: "jane@example.com"}
|
|
if errs := Validate(r, "newsletter"); len(errs) > 0 {
|
|
t.Fatalf("expected no errors, got %v", errs)
|
|
}
|
|
}
|
|
|
|
func TestValidateNewsletter_RequiresEmail(t *testing.T) {
|
|
r := &Request{Email: "garbage"}
|
|
errs := Validate(r, "newsletter")
|
|
if len(errs) == 0 {
|
|
t.Fatal("expected error for missing/invalid email")
|
|
}
|
|
}
|
|
|
|
func TestValidateNewsletter_IgnoresNameAndMessage(t *testing.T) {
|
|
// Newsletter type only cares about the email field.
|
|
r := &Request{Email: "jane@example.com", Name: "", Message: ""}
|
|
if errs := Validate(r, "newsletter"); len(errs) > 0 {
|
|
t.Fatalf("newsletter should ignore empty name/message, got %v", errs)
|
|
}
|
|
}
|
|
|
|
func TestValidateRejectsUnknownTypeOnlyWhenTypeExplicitlyInvalid(t *testing.T) {
|
|
// Sanity: an unsupported form type (e.g. "foo") falls back to contact
|
|
// validation, not to a hard error. The hard error is enforced at the
|
|
// config layer, not in Validate itself.
|
|
r := &Request{Name: "Jane", Email: "jane@example.com", Message: "Hello there."}
|
|
if errs := Validate(r, "foo"); len(errs) > 0 {
|
|
t.Fatalf("Validate with unknown type should fall back to contact, got %v", errs)
|
|
}
|
|
}
|
|
|
|
func TestValidateTrimsWhitespace(t *testing.T) {
|
|
r := &Request{
|
|
Name: " Jane ",
|
|
Email: " jane@example.com ",
|
|
Service: " architecture ",
|
|
Message: " hello there ",
|
|
}
|
|
if errs := Validate(r, "contact"); len(errs) > 0 {
|
|
t.Fatalf("expected no errors, got %v", errs)
|
|
}
|
|
if r.Name != "Jane" || r.Email != "jane@example.com" || r.Message != "hello there" {
|
|
t.Errorf("expected whitespace to be trimmed, got %+v", r)
|
|
}
|
|
}
|
|
|
|
func TestErrorMessageHasMinLengthPlaceholder(t *testing.T) {
|
|
// Sanity: the minLength error message in the en.json UI mirror should
|
|
// remain a simple string. Here we just check that error messages are
|
|
// human-readable, not empty.
|
|
r := &Request{Name: "J", Email: "jane@example.com", Message: "hi"}
|
|
errs := Validate(r, "contact")
|
|
if len(errs) < 2 {
|
|
t.Fatalf("expected at least 2 errors, got %v", errs)
|
|
}
|
|
for _, e := range errs {
|
|
if strings.TrimSpace(e.Message) == "" {
|
|
t.Errorf("error message is empty for field %q", e.Field)
|
|
}
|
|
}
|
|
}
|