Introduce a commercial license option alongside AGPL-3.0-only, require a CLA for contributors, and document the terms in COMMERCIAL.md and NOTICE. Add a script to stamp SPDX headers on Go files and apply it across the tree.
145 lines
4.4 KiB
Go
145 lines
4.4 KiB
Go
// 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)
|
|
}
|
|
}
|
|
}
|