// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial // SPDX-FileCopyrightText: 2025-2026 Christian Galo package forms import "testing" // The dense fraction ladder (design D1, D2): every control's natural rung, // the two steps a declaration may take from it, and the column class each // rung renders. CheckInvariants and Render both call FieldFraction, so // these tests pin the one function both rely on. func TestControlFraction(t *testing.T) { for _, tc := range []struct { control Control want Fraction }{ {Number, FractionSixth}, {Date, FractionSixth}, {DateTime, FractionQuarter}, {Select, FractionThird}, {Text, FractionThird}, {Email, FractionThird}, {URL, FractionThird}, {Textarea, FractionFull}, {Checkbox, FractionNone}, {Radio, FractionNone}, {Static, FractionNone}, {Hidden, FractionNone}, } { if got := tc.control.Fraction(); got != tc.want { t.Errorf("%s.Fraction() = %v, want %v", tc.control, got, tc.want) } } } func TestFractionColClass(t *testing.T) { for _, tc := range []struct { fraction Fraction want string }{ {FractionSixth, "col-12 col-xl-2"}, {FractionQuarter, "col-12 col-xl-3"}, {FractionThird, "col-12 col-xl-4"}, {FractionHalf, "col-12 col-xl-6"}, {FractionFull, "col-12"}, {FractionNone, ""}, } { if got := tc.fraction.ColClass(); got != tc.want { t.Errorf("%v.ColClass() = %q, want %q", tc.fraction, got, tc.want) } } } func TestWidthValid(t *testing.T) { for _, tc := range []struct { width Width want bool }{ {"", true}, {WidthNarrower, true}, {WidthWider, true}, {"narrow", false}, {"wide", false}, {"auto", false}, } { if got := tc.width.Valid(); got != tc.want { t.Errorf("Width(%q).Valid() = %v, want %v", tc.width, got, tc.want) } } } // The zero Width always resolves to the control's own rung. func TestFieldFractionZeroWidthIsTheNaturalRung(t *testing.T) { for _, c := range []Control{Number, Date, DateTime, Select, Text, Email, URL, Textarea, Checkbox, Radio, Static, Hidden} { fraction, ok := FieldFraction(c, "") if !ok { t.Errorf("FieldFraction(%s, \"\") not ok", c) } if fraction != c.Fraction() { t.Errorf("FieldFraction(%s, \"\") = %v, want its own rung %v", c, fraction, c.Fraction()) } } } // A step below a sixth, the ladder's bottom rung, leaves the ladder. func TestFieldFractionNarrowerBelowSixthIsRefused(t *testing.T) { for _, c := range []Control{Number, Date} { if _, ok := FieldFraction(c, WidthNarrower); ok { t.Errorf("FieldFraction(%s, WidthNarrower) must leave the ladder", c) } } } // A control that stands on no rung has nothing to step from, textarea // included: its full row is the control's own, not a step. func TestFieldFractionNoRungRefusesBothSteps(t *testing.T) { for _, c := range []Control{Checkbox, Radio, Static, Hidden, Textarea} { for _, w := range []Width{WidthNarrower, WidthWider} { if _, ok := FieldFraction(c, w); ok { t.Errorf("FieldFraction(%s, %s) must be refused, control stands on no rung", c, w) } } } } // A wider step from a half would reach a full row, which no control's // natural rung actually sits at (the highest a wider step reaches through // FieldFraction is a half, from a third); stepFraction's own edge is // tested directly since no Control exercises it. func TestStepFractionAboveHalfIsRefused(t *testing.T) { if _, ok := stepFraction(FractionHalf, WidthWider); ok { t.Error("a wider step from a half must leave the ladder") } } // The steps a real declaration takes: a select or a text control narrower // (a code, a short enum) lands on a quarter; wider lands on a half. A // date-time steps either way onto a sixth or a third. func TestFieldFractionValidSteps(t *testing.T) { for _, tc := range []struct { control Control width Width want Fraction }{ {Select, WidthNarrower, FractionQuarter}, {Text, WidthNarrower, FractionQuarter}, {Select, WidthWider, FractionHalf}, {Text, WidthWider, FractionHalf}, {DateTime, WidthNarrower, FractionSixth}, {DateTime, WidthWider, FractionThird}, {Number, WidthWider, FractionQuarter}, {Date, WidthWider, FractionQuarter}, } { fraction, ok := FieldFraction(tc.control, tc.width) if !ok { t.Errorf("FieldFraction(%s, %s) refused, want %v", tc.control, tc.width, tc.want) continue } if fraction != tc.want { t.Errorf("FieldFraction(%s, %s) = %v, want %v", tc.control, tc.width, fraction, tc.want) } } }