feat(lagoon): check min and max as character length on string and url fields (quick-261104-f4x)

- on a string or url field that is not numeric or integer, min and max
  compare utf8.RuneCountInString (Laravel's mb_strlen) and answer with
  the lagoon::validation min.string / max.string messages
- a min or max argument that is not a whole number is the
  unrecognized-rule error, whatever the value
- rule strings without string or url keep their results (pinned by a
  test); between is unchanged
This commit is contained in:
Jakub Zych
2026-11-04 11:13:09 +01:00
parent d2ce3a2c3b
commit d166f1c308
5 changed files with 109 additions and 4 deletions

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"reflect"
"strings"
"testing"
"testing/fstest"
@@ -59,6 +60,7 @@ func TestSettingsStringURLRules(t *testing.T) {
{"empty website", map[string]any{"website": ""}, nil},
{"null website and title", map[string]any{"website": nil, "title": nil}, nil},
{"invalid website", map[string]any{"website": "not a url"}, map[string][]string{"website": {"The website format is invalid."}}},
{"title too long", map[string]any{"title": strings.Repeat("a", 256)}, map[string][]string{"title": {"The title may not be greater than 255 characters."}}},
}
for _, tc := range cases {
model := &stringURLSettings{}
@@ -117,4 +119,18 @@ func TestSettingsStringURLRulesPostgres(t *testing.T) {
if stored.Website == nil || *stored.Website != feedURL {
t.Fatalf("stored website = %v", stored.Website)
}
_, err = svc.Put(ctx, setting, map[string]any{"title": strings.Repeat("a", 256)})
if !errors.As(err, &invalid) {
t.Fatalf("long title error = %T %v", err, err)
}
if got, _ := invalid.Details["title"].([]string); !reflect.DeepEqual(got, []string{"The title may not be greater than 255 characters."}) {
t.Fatalf("details = %#v", invalid.Details)
}
stored = stringURLSettings{}
if err := db.First(&stored, 1).Error; err != nil {
t.Fatal(err)
}
if stored.Title == nil || *stored.Title != "Feed" {
t.Fatalf("stored title = %v", stored.Title)
}
}