From 5b51bff4e63d97b9e1f7f876012290285caa7c12 Mon Sep 17 00:00:00 2001 From: Pantelis Sampaziotis Date: Wed, 5 Feb 2020 22:39:47 +0200 Subject: [PATCH] Add isLowercase and isUppercase valitation --- baked_in.go | 24 +++++++++++++ doc.go | 12 +++++++ translations/en/en.go | 10 ++++++ translations/en/en_test.go | 15 +++++++- validator_test.go | 74 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 134 insertions(+), 1 deletion(-) diff --git a/baked_in.go b/baked_in.go index 9eff0e4..57440cb 100644 --- a/baked_in.go +++ b/baked_in.go @@ -166,6 +166,8 @@ var ( "html_encoded": isHTMLEncoded, "url_encoded": isURLEncoded, "dir": isDir, + "lowercase": isLowercase, + "uppercase": isUppercase, } ) @@ -2007,3 +2009,25 @@ func isDir(fl FieldLevel) bool { panic(fmt.Sprintf("Bad field type %T", field.Interface())) } + +// isLowercase is the validation function for validating if the current field's value is a lowercase string. +func isLowercase(fl FieldLevel) bool { + field := fl.Field() + + if field.Kind() == reflect.String { + return field.String() == strings.ToLower(field.String()) + } + + panic(fmt.Sprintf("Bad field type %T", field.Interface())) +} + +// isUppercase is the validation function for validating if the current field's value is an uppercase string. +func isUppercase(fl FieldLevel) bool { + field := fl.Field() + + if field.Kind() == reflect.String { + return field.String() == strings.ToUpper(field.String()) + } + + panic(fmt.Sprintf("Bad field type %T", field.Interface())) +} diff --git a/doc.go b/doc.go index 799882c..85f0507 100644 --- a/doc.go +++ b/doc.go @@ -641,6 +641,18 @@ hashtag (#) Usage: hexcolor +Lowercase String + +This validates that a string value contains only lowercase characters. An empty string is considered a valid lowercase string. + + Usage: lowercase + +Uppercase String + +This validates that a string value contains only uppercase characters. An empty string is considered a valid uppercase string. + + Usage: uppercase + RGB String This validates that a string value contains a valid rgb color diff --git a/translations/en/en.go b/translations/en/en.go index 3b1058b..cf89fd2 100644 --- a/translations/en/en.go +++ b/translations/en/en.go @@ -1321,6 +1321,16 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er return s }, }, + { + tag: "lowercase", + translation: "{0} must be a lowercase string", + override: false, + }, + { + tag: "uppercase", + translation: "{0} must be an uppercase string", + override: false, + }, } for _, t := range translations { diff --git a/translations/en/en_test.go b/translations/en/en_test.go index cddcb84..769409a 100644 --- a/translations/en/en_test.go +++ b/translations/en/en_test.go @@ -4,9 +4,9 @@ import ( "testing" "time" + . "github.com/go-playground/assert/v2" english "github.com/go-playground/locales/en" ut "github.com/go-playground/universal-translator" - . "github.com/go-playground/assert/v2" "github.com/go-playground/validator/v10" ) @@ -141,6 +141,8 @@ func TestTranslations(t *testing.T) { UniqueSlice []string `validate:"unique"` UniqueArray [3]string `validate:"unique"` UniqueMap map[string]string `validate:"unique"` + LowercaseString string `validate:"lowercase"` + UppercaseString string `validate:"uppercase"` } var test Test @@ -183,6 +185,9 @@ func TestTranslations(t *testing.T) { test.MultiByte = "1234feerf" + test.LowercaseString = "ABCDEFG" + test.UppercaseString = "abcdefg" + s := "toolong" test.StrPtrMaxLen = &s test.StrPtrLen = &s @@ -632,6 +637,14 @@ func TestTranslations(t *testing.T) { ns: "Test.UniqueMap", expected: "UniqueMap must contain unique values", }, + { + ns: "Test.LowercaseString", + expected: "LowercaseString must be a lowercase string", + }, + { + ns: "Test.UppercaseString", + expected: "UppercaseString must be an uppercase string", + }, } for _, tt := range tests { diff --git a/validator_test.go b/validator_test.go index 2c8b96b..1114071 100644 --- a/validator_test.go +++ b/validator_test.go @@ -9003,3 +9003,77 @@ func TestGetTag(t *testing.T) { Equal(t, errs, nil) Equal(t, tag, "mytag") } + +func TestLowercaseValidation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {`abcdefg`, true}, + {`Abcdefg`, false}, + {"", true}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "lowercase") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d lowercase failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d lowercase failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "lowercase" { + t.Fatalf("Index: %d lowercase failed Error: %s", i, errs) + } + } + } + } + + PanicMatches(t, func() { + _ = validate.Var(2, "lowercase") + }, "Bad field type int") +} + +func TestUppercaseValidation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {`ABCDEFG`, true}, + {`aBCDEFG`, false}, + {"", true}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "uppercase") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d uppercase failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d uppercase failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "uppercase" { + t.Fatalf("Index: %d uppercase failed Error: %s", i, errs) + } + } + } + } + + PanicMatches(t, func() { + _ = validate.Var(2, "uppercase") + }, "Bad field type int") +}