package customfields import ( "strings" "testing" ) func textDef(key string, required bool) FieldDefinition { return FieldDefinition{FieldKey: key, Label: "Text " + key, FieldType: "text", Required: required, IsActive: true} } func TestValidateValuesUnknownKeyRejected(t *testing.T) { _, err := ValidateValues([]FieldDefinition{textDef("a", false)}, map[string]any{"b": "x"}, false) if err == nil { t.Fatal("expected error for unknown field key") } } func TestValidateValuesRequiredMissingRejectedOnlyWhenEnforced(t *testing.T) { defs := []FieldDefinition{textDef("a", true)} if _, err := ValidateValues(defs, map[string]any{}, true); err == nil { t.Error("expected error: required field missing, enforceRequired=true") } if _, err := ValidateValues(defs, map[string]any{}, false); err != nil { t.Errorf("unexpected error with enforceRequired=false: %v", err) } } func TestValidateValuesRequiredEmptyStringRejected(t *testing.T) { defs := []FieldDefinition{textDef("a", true)} if _, err := ValidateValues(defs, map[string]any{"a": " "}, true); err == nil { t.Error("expected error: required field present but blank") } } func TestValidateValuesTextTypeMismatchRejected(t *testing.T) { defs := []FieldDefinition{textDef("a", false)} if _, err := ValidateValues(defs, map[string]any{"a": 5.0}, false); err == nil { t.Error("expected error: number given for a text field") } } func TestValidateValuesTextTooLongRejected(t *testing.T) { defs := []FieldDefinition{textDef("a", false)} long := strings.Repeat("a", MaxTextValueLen+1) if _, err := ValidateValues(defs, map[string]any{"a": long}, false); err == nil { t.Error("expected error: text value over MaxTextValueLen") } } func TestValidateValuesNumberType(t *testing.T) { defs := []FieldDefinition{{FieldKey: "n", FieldType: "number", IsActive: true}} if _, err := ValidateValues(defs, map[string]any{"n": "not a number"}, false); err == nil { t.Error("expected error: string given for a number field") } out, err := ValidateValues(defs, map[string]any{"n": 42.5}, false) if err != nil { t.Fatalf("unexpected error: %v", err) } if out["n"] != 42.5 { t.Errorf("n = %v, want 42.5", out["n"]) } } func TestValidateValuesCheckboxType(t *testing.T) { defs := []FieldDefinition{{FieldKey: "c", FieldType: "checkbox", IsActive: true}} if _, err := ValidateValues(defs, map[string]any{"c": "true"}, false); err == nil { t.Error("expected error: string given for a checkbox field") } out, err := ValidateValues(defs, map[string]any{"c": true}, false) if err != nil { t.Fatalf("unexpected error: %v", err) } if out["c"] != true { t.Errorf("c = %v, want true", out["c"]) } } func TestValidateValuesSelectType(t *testing.T) { defs := []FieldDefinition{{FieldKey: "s", FieldType: "select", Options: []string{"red", "blue"}, IsActive: true}} if _, err := ValidateValues(defs, map[string]any{"s": "green"}, false); err == nil { t.Error("expected error: value not in options list") } out, err := ValidateValues(defs, map[string]any{"s": "blue"}, false) if err != nil { t.Fatalf("unexpected error: %v", err) } if out["s"] != "blue" { t.Errorf("s = %v, want blue", out["s"]) } } func TestValidateValuesArchivedFieldRejectedAsUnknown(t *testing.T) { // Fetch (see fetch.go) only ever passes active defs in, so an archived // field's key is indistinguishable from a key that was never defined — // exactly the behavior order.Update relies on to leave an archived // field's already-stored value alone: it must never appear as a valid // target for a NEW write. archived := FieldDefinition{FieldKey: "old", FieldType: "text", IsActive: false} if _, err := ValidateValues([]FieldDefinition{archived}, map[string]any{"old": "x"}, false); err == nil { t.Error("expected error: archived field must not be a valid write target") } }