go-html/responsive_test.go
Virgil 1d71ac4676
Some checks are pending
Security Scan / security (push) Waiting to run
Test / test (push) Waiting to run
fix(html): harden nil-safe pipeline rendering
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-03 17:06:27 +00:00

157 lines
4.3 KiB
Go

package html
import (
"strings"
"testing"
)
func TestResponsive_SingleVariant(t *testing.T) {
ctx := NewContext()
r := NewResponsive().
Variant("desktop", NewLayout("HLCRF").
H(Raw("header")).L(Raw("nav")).C(Raw("main")).R(Raw("aside")).F(Raw("footer")))
got := r.Render(ctx)
if !strings.Contains(got, `data-variant="desktop"`) {
t.Errorf("responsive should contain data-variant, got:\n%s", got)
}
if !strings.Contains(got, `data-block="H-0"`) {
t.Errorf("responsive should contain layout content, got:\n%s", got)
}
}
func TestResponsive_MultiVariant(t *testing.T) {
ctx := NewContext()
r := NewResponsive().
Variant("desktop", NewLayout("HLCRF").H(Raw("h")).L(Raw("l")).C(Raw("c")).R(Raw("r")).F(Raw("f"))).
Variant("tablet", NewLayout("HCF").H(Raw("h")).C(Raw("c")).F(Raw("f"))).
Variant("mobile", NewLayout("C").C(Raw("c")))
got := r.Render(ctx)
for _, v := range []string{"desktop", "tablet", "mobile"} {
if !strings.Contains(got, `data-variant="`+v+`"`) {
t.Errorf("responsive missing variant %q in:\n%s", v, got)
}
}
}
func TestResponsive_VariantOrder(t *testing.T) {
ctx := NewContext()
r := NewResponsive().
Variant("desktop", NewLayout("HLCRF").C(Raw("d"))).
Variant("mobile", NewLayout("C").C(Raw("m")))
got := r.Render(ctx)
di := strings.Index(got, `data-variant="desktop"`)
mi := strings.Index(got, `data-variant="mobile"`)
if di < 0 || mi < 0 {
t.Fatalf("missing variants in:\n%s", got)
}
if di >= mi {
t.Errorf("desktop should appear before mobile (insertion order), desktop=%d mobile=%d", di, mi)
}
}
func TestResponsive_NestedPaths(t *testing.T) {
ctx := NewContext()
inner := NewLayout("HCF").H(Raw("ih")).C(Raw("ic")).F(Raw("if"))
r := NewResponsive().
Variant("desktop", NewLayout("HLCRF").C(inner))
got := r.Render(ctx)
if !strings.Contains(got, `data-block="C-0-H-0"`) {
t.Errorf("nested layout in responsive variant missing C-0-H-0 in:\n%s", got)
}
if !strings.Contains(got, `data-block="C-0-C-0"`) {
t.Errorf("nested layout in responsive variant missing C-0-C-0 in:\n%s", got)
}
}
func TestResponsive_VariantsIndependent(t *testing.T) {
ctx := NewContext()
r := NewResponsive().
Variant("a", NewLayout("HLCRF").C(Raw("content-a"))).
Variant("b", NewLayout("HCF").C(Raw("content-b")))
got := r.Render(ctx)
count := strings.Count(got, `data-block="C-0"`)
if count != 2 {
t.Errorf("expected 2 independent C-0 blocks, got %d in:\n%s", count, got)
}
}
func TestResponsive_ImplementsNode(t *testing.T) {
var _ Node = NewResponsive()
}
func TestResponsive_RenderNilReceiver(t *testing.T) {
var r *Responsive
got := r.Render(NewContext())
if got != "" {
t.Fatalf("nil Responsive should render empty string, got %q", got)
}
}
func TestResponsive_NilLayoutVariant(t *testing.T) {
ctx := NewContext()
r := NewResponsive().
Variant("desktop", nil).
Variant("mobile", NewLayout("C").C(Raw("m")))
got := r.Render(ctx)
if !strings.Contains(got, `data-variant="desktop"`) {
t.Fatalf("nil layout variant should still render its wrapper, got:\n%s", got)
}
if strings.Contains(got, "<nil>") {
t.Fatalf("nil layout variant should not render placeholder text, got:\n%s", got)
}
if !strings.Contains(got, `data-variant="mobile"`) {
t.Fatalf("responsive should still render subsequent variants, got:\n%s", got)
}
}
func TestVariantSelector(t *testing.T) {
tests := []struct {
name string
variant string
want string
}{
{name: "plain", variant: "desktop", want: `[data-variant="desktop"]`},
{name: "escaped", variant: `desk"top\` + "\n" + `line`, want: `[data-variant="desk\"top\\\a line"]`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := VariantSelector(tt.variant)
if got != tt.want {
t.Fatalf("VariantSelector(%q) = %q, want %q", tt.variant, got, tt.want)
}
})
}
}
func TestScopeVariant(t *testing.T) {
tests := []struct {
name string
variant string
selector string
want string
}{
{name: "scope", variant: "desktop", selector: ".nav", want: `[data-variant="desktop"] .nav`},
{name: "empty selector", variant: "mobile", selector: "", want: `[data-variant="mobile"]`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ScopeVariant(tt.variant, tt.selector)
if got != tt.want {
t.Fatalf("ScopeVariant(%q, %q) = %q, want %q", tt.variant, tt.selector, got, tt.want)
}
})
}
}