From 3945da16ee820591754b888b40b1361fb112ed66 Mon Sep 17 00:00:00 2001 From: Tyler Cipriani Date: Fri, 15 Mar 2019 15:21:21 -0600 Subject: [PATCH] Add `startswith` and `endswith` validators `HasPrefix` and `HasSuffix` are both part of the `strings` package. These seem like generally useful validations to include and cover some subset of the use-cases of a general regex validator without having any of the problems outlined by the validator docs. --- baked_in.go | 12 ++++++++++ doc.go | 12 ++++++++++ validator_test.go | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/baked_in.go b/baked_in.go index 52729b8..702e78d 100644 --- a/baked_in.go +++ b/baked_in.go @@ -112,6 +112,8 @@ var ( "excludes": excludes, "excludesall": excludesAll, "excludesrune": excludesRune, + "startswith": startsWith, + "endswith": endsWith, "isbn": isISBN, "isbn10": isISBN10, "isbn13": isISBN13, @@ -650,6 +652,16 @@ func contains(fl FieldLevel) bool { return strings.Contains(fl.Field().String(), fl.Param()) } +// StartsWith is the validation function for validating that the field's value starts with the text specified within the param. +func startsWith(fl FieldLevel) bool { + return strings.HasPrefix(fl.Field().String(), fl.Param()) +} + +// EndsWith is the validation function for validating that the field's value ends with the text specified within the param. +func endsWith(fl FieldLevel) bool { + return strings.HasSuffix(fl.Field().String(), fl.Param()) +} + // FieldContains is the validation function for validating if the current field's value contains the field specified by the param's value. func fieldContains(fl FieldLevel) bool { field := fl.Field() diff --git a/doc.go b/doc.go index 0bc27a1..5ce3800 100644 --- a/doc.go +++ b/doc.go @@ -714,6 +714,18 @@ This validates that a string value does not contain the supplied rune value. Usage: excludesrune=@ +Starts With + +This validates that a string value starts with the supplied string value + + Usage: startswith=hello + +Ends With + +This validates that a string value ends with the supplied string value + + Usage: endswith=goodbye + International Standard Book Number This validates that a string value contains a valid isbn10 or isbn13 value. diff --git a/validator_test.go b/validator_test.go index aded71f..86cfd5c 100644 --- a/validator_test.go +++ b/validator_test.go @@ -8555,3 +8555,59 @@ func TestDirValidation(t *testing.T) { validate.Var(2, "dir") }, "Bad field type int") } + +func TestStartsWithValidation(t *testing.T) { + tests := []struct { + Value string `validate:"startswith=(/^ヮ^)/*:・゚✧"` + Tag string + ExpectedNil bool + }{ + {Value: "(/^ヮ^)/*:・゚✧ glitter", Tag: "startswith=(/^ヮ^)/*:・゚✧", ExpectedNil: true}, + {Value: "abcd", Tag: "startswith=(/^ヮ^)/*:・゚✧", ExpectedNil: false}, + } + + validate := New() + + for i, s := range tests { + errs := validate.Var(s.Value, s.Tag) + + if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { + t.Fatalf("Index: %d failed Error: %s", i, errs) + } + + errs = validate.Struct(s) + + if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { + t.Fatalf("Index: %d failed Error: %s", i, errs) + } + } +} + +func TestEndsWithValidation(t *testing.T) { + tests := []struct { + Value string `validate:"endswith=(/^ヮ^)/*:・゚✧"` + Tag string + ExpectedNil bool + }{ + {Value: "glitter (/^ヮ^)/*:・゚✧", Tag: "endswith=(/^ヮ^)/*:・゚✧", ExpectedNil: true}, + {Value: "(/^ヮ^)/*:・゚✧ glitter", Tag: "endswith=(/^ヮ^)/*:・゚✧", ExpectedNil: false}, + } + + validate := New() + + for i, s := range tests { + errs := validate.Var(s.Value, s.Tag) + + if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { + t.Fatalf("Index: %d failed Error: %s", i, errs) + } + + errs = validate.Struct(s) + + if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { + t.Fatalf("Index: %d failed Error: %s", i, errs) + } + } +} + +