Adding upstream version 1.0.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
5ca5eb8df5
commit
4a5c02e4d1
19 changed files with 3254 additions and 0 deletions
613
validate_test.go
Executable file
613
validate_test.go
Executable file
|
@ -0,0 +1,613 @@
|
|||
// Copyright 2014 Martini Authors
|
||||
// Copyright 2014 The Macaron Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package binding
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
chi "github.com/go-chi/chi/v5"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var (
|
||||
emptyStr = ""
|
||||
urlStr = "http://example.com/"
|
||||
alphaDashStr = "aB-12"
|
||||
idInt = 1
|
||||
)
|
||||
|
||||
var validationTestCases = []validationTestCase{
|
||||
{
|
||||
description: "No errors",
|
||||
data: BlogPost{
|
||||
Id: 1,
|
||||
Post: Post{
|
||||
Title: "Behold The Title!",
|
||||
Content: "And some content",
|
||||
},
|
||||
Author: Person{
|
||||
Name: "Matt Holt",
|
||||
},
|
||||
},
|
||||
expectedErrors: Errors{},
|
||||
},
|
||||
{
|
||||
description: "ID required",
|
||||
data: BlogPost{
|
||||
Post: Post{
|
||||
Title: "Behold The Title!",
|
||||
Content: "And some content",
|
||||
},
|
||||
Author: Person{
|
||||
Name: "Matt Holt",
|
||||
},
|
||||
},
|
||||
expectedErrors: Errors{
|
||||
Error{
|
||||
FieldNames: []string{"id"},
|
||||
Classification: ERR_REQUIRED,
|
||||
Message: "Required",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Embedded struct field required",
|
||||
data: BlogPost{
|
||||
Id: 1,
|
||||
Post: Post{
|
||||
Content: "Content given, but title is required",
|
||||
},
|
||||
Author: Person{
|
||||
Name: "Matt Holt",
|
||||
},
|
||||
},
|
||||
expectedErrors: Errors{
|
||||
Error{
|
||||
FieldNames: []string{"title"},
|
||||
Classification: ERR_REQUIRED,
|
||||
Message: "Required",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"title"},
|
||||
Classification: "LengthError",
|
||||
Message: "Life is too short",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Nested struct field required",
|
||||
data: BlogPost{
|
||||
Id: 1,
|
||||
Post: Post{
|
||||
Title: "Behold The Title!",
|
||||
Content: "And some content",
|
||||
},
|
||||
},
|
||||
expectedErrors: Errors{
|
||||
Error{
|
||||
FieldNames: []string{"name"},
|
||||
Classification: ERR_REQUIRED,
|
||||
Message: "Required",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Required field missing in nested struct pointer",
|
||||
data: BlogPost{
|
||||
Id: 1,
|
||||
Post: Post{
|
||||
Title: "Behold The Title!",
|
||||
Content: "And some content",
|
||||
},
|
||||
Author: Person{
|
||||
Name: "Matt Holt",
|
||||
},
|
||||
Coauthor: &Person{},
|
||||
},
|
||||
expectedErrors: Errors{
|
||||
Error{
|
||||
FieldNames: []string{"name"},
|
||||
Classification: ERR_REQUIRED,
|
||||
Message: "Required",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "All required fields specified in nested struct pointer",
|
||||
data: BlogPost{
|
||||
Id: 1,
|
||||
Post: Post{
|
||||
Title: "Behold The Title!",
|
||||
Content: "And some content",
|
||||
},
|
||||
Author: Person{
|
||||
Name: "Matt Holt",
|
||||
},
|
||||
Coauthor: &Person{
|
||||
Name: "Jeremy Saenz",
|
||||
},
|
||||
},
|
||||
expectedErrors: Errors{},
|
||||
},
|
||||
{
|
||||
description: "Custom validation should put an error",
|
||||
data: BlogPost{
|
||||
Id: 1,
|
||||
Post: Post{
|
||||
Title: "Too short",
|
||||
Content: "And some content",
|
||||
},
|
||||
Author: Person{
|
||||
Name: "Matt Holt",
|
||||
},
|
||||
},
|
||||
expectedErrors: Errors{
|
||||
Error{
|
||||
FieldNames: []string{"title"},
|
||||
Classification: "LengthError",
|
||||
Message: "Life is too short",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "List Validation",
|
||||
data: []BlogPost{
|
||||
{
|
||||
Id: 1,
|
||||
Post: Post{
|
||||
Title: "First Post",
|
||||
Content: "And some content",
|
||||
},
|
||||
Author: Person{
|
||||
Name: "Leeor Aharon",
|
||||
},
|
||||
},
|
||||
{
|
||||
Id: 2,
|
||||
Post: Post{
|
||||
Title: "Second Post",
|
||||
Content: "And some content",
|
||||
},
|
||||
Author: Person{
|
||||
Name: "Leeor Aharon",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErrors: Errors{},
|
||||
},
|
||||
{
|
||||
description: "List Validation w/ Errors",
|
||||
data: []BlogPost{
|
||||
{
|
||||
Id: 1,
|
||||
Post: Post{
|
||||
Title: "First Post",
|
||||
Content: "And some content",
|
||||
},
|
||||
Author: Person{
|
||||
Name: "Leeor Aharon",
|
||||
},
|
||||
},
|
||||
{
|
||||
Id: 2,
|
||||
Post: Post{
|
||||
Title: "Too Short",
|
||||
Content: "And some content",
|
||||
},
|
||||
Author: Person{
|
||||
Name: "Leeor Aharon",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErrors: Errors{
|
||||
Error{
|
||||
FieldNames: []string{"title"},
|
||||
Classification: "LengthError",
|
||||
Message: "Life is too short",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "List of invalid custom validations",
|
||||
data: []SadForm{
|
||||
{
|
||||
AlphaDash: ",",
|
||||
AlphaDashDot: ",",
|
||||
Size: "123",
|
||||
SizeSlice: []string{"1", "2", "3"},
|
||||
MinSize: ",",
|
||||
MinSizeSlice: []string{",", ","},
|
||||
MaxSize: ",,",
|
||||
MaxSizeSlice: []string{",", ","},
|
||||
Range: 3,
|
||||
Email: ",",
|
||||
URL: ",",
|
||||
URLEmpty: "",
|
||||
InInvalid: "4",
|
||||
NotIn: "1",
|
||||
Include: "def",
|
||||
Exclude: "abc",
|
||||
},
|
||||
},
|
||||
expectedErrors: Errors{
|
||||
Error{
|
||||
FieldNames: []string{"AlphaDash"},
|
||||
Classification: "AlphaDashError",
|
||||
Message: "AlphaDash",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"AlphaDashDot"},
|
||||
Classification: "AlphaDashDot",
|
||||
Message: "AlphaDashDot",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"Size"},
|
||||
Classification: "Size",
|
||||
Message: "Size",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"Size"},
|
||||
Classification: "Size",
|
||||
Message: "Size",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"MinSize"},
|
||||
Classification: "MinSize",
|
||||
Message: "MinSize",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"MinSize"},
|
||||
Classification: "MinSize",
|
||||
Message: "MinSize",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"MaxSize"},
|
||||
Classification: "MaxSize",
|
||||
Message: "MaxSize",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"MaxSize"},
|
||||
Classification: "MaxSize",
|
||||
Message: "MaxSize",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"Range"},
|
||||
Classification: "Range",
|
||||
Message: "Range",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"Email"},
|
||||
Classification: "Email",
|
||||
Message: "Email",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"Url"},
|
||||
Classification: "Url",
|
||||
Message: "Url",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"Default"},
|
||||
Classification: "Default",
|
||||
Message: "Default",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"InInvalid"},
|
||||
Classification: "In",
|
||||
Message: "In",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"NotIn"},
|
||||
Classification: "NotIn",
|
||||
Message: "NotIn",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"Include"},
|
||||
Classification: "Include",
|
||||
Message: "Include",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"Exclude"},
|
||||
Classification: "Exclude",
|
||||
Message: "Exclude",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "List of valid custom validations",
|
||||
data: []SadForm{
|
||||
{
|
||||
AlphaDash: "123-456",
|
||||
AlphaDashDot: "123.456",
|
||||
Size: "1",
|
||||
SizeSlice: []string{"1"},
|
||||
MinSize: "12345",
|
||||
MinSizeSlice: []string{"1", "2", "3", "4", "5"},
|
||||
MaxSize: "1",
|
||||
MaxSizeSlice: []string{"1"},
|
||||
Range: 2,
|
||||
In: "1",
|
||||
InInvalid: "1",
|
||||
Email: "123@456.com",
|
||||
URL: "http://123.456",
|
||||
Include: "abc",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "slice of structs Validation",
|
||||
data: Group{
|
||||
Name: "group1",
|
||||
People: []Person{
|
||||
{Name: "anthony"},
|
||||
{Name: "awoods"},
|
||||
},
|
||||
},
|
||||
expectedErrors: Errors{},
|
||||
},
|
||||
{
|
||||
description: "slice of structs Validation failer",
|
||||
data: Group{
|
||||
Name: "group1",
|
||||
People: []Person{
|
||||
{Name: "anthony"},
|
||||
{Name: ""},
|
||||
},
|
||||
},
|
||||
expectedErrors: Errors{
|
||||
Error{
|
||||
FieldNames: []string{"name"},
|
||||
Classification: ERR_REQUIRED,
|
||||
Message: "Required",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "email fail",
|
||||
data: struct {
|
||||
EmailValid string `binding:"Email"`
|
||||
EmailFail string `binding:"Email"`
|
||||
EmailFail2 string `binding:"Email"`
|
||||
EmailFail3 string `binding:"Email"`
|
||||
}{
|
||||
EmailValid: "123@asd.com",
|
||||
EmailFail: "test 123@asd.com",
|
||||
EmailFail2: "123@asd.com test",
|
||||
EmailFail3: "test 123@asd.com test",
|
||||
},
|
||||
expectedErrors: Errors{
|
||||
Error{
|
||||
FieldNames: []string{"EmailFail"},
|
||||
Classification: ERR_EMAIL,
|
||||
Message: "Email",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"EmailFail2"},
|
||||
Classification: ERR_EMAIL,
|
||||
Message: "Email",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"EmailFail3"},
|
||||
Classification: ERR_EMAIL,
|
||||
Message: "Email",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "pointer form empty and nil",
|
||||
data: PointerForm{},
|
||||
expectedErrors: Errors{},
|
||||
},
|
||||
{
|
||||
description: "pointer form empty",
|
||||
data: PointerForm{
|
||||
URL: "",
|
||||
URLPointer: &emptyStr,
|
||||
AlphaDash: "",
|
||||
AlphaDashPointer: &emptyStr,
|
||||
},
|
||||
expectedErrors: Errors{},
|
||||
},
|
||||
{
|
||||
description: "no errors with not required fields",
|
||||
data: []*struct {
|
||||
AlphaDash string `binding:"AlphaDash"`
|
||||
AlphaDashDot string `binding:"AlphaDashDot"`
|
||||
Size string `binding:"Size(1)"`
|
||||
SizeSlice []string `binding:"Size(1)"`
|
||||
MinSize string `binding:"MinSize(5)"`
|
||||
MinSizeSlice []string `binding:"MinSize(5)"`
|
||||
MaxSize string `binding:"MaxSize(1)"`
|
||||
MaxSizeSlice []string `binding:"MaxSize(1)"`
|
||||
Range int `binding:"Range(1,2)"`
|
||||
Email string `binding:"Email"`
|
||||
URL string `binding:"Url"`
|
||||
In string `binding:"Default(0);In(1,2,3)"`
|
||||
NotIn string `binding:"NotIn(1,2,3)"`
|
||||
}{
|
||||
{},
|
||||
},
|
||||
expectedErrors: Errors{},
|
||||
},
|
||||
{
|
||||
description: "pointer form with valid data",
|
||||
data: PointerForm{
|
||||
URL: urlStr,
|
||||
URLPointer: &urlStr,
|
||||
AlphaDash: alphaDashStr,
|
||||
AlphaDashPointer: &alphaDashStr,
|
||||
},
|
||||
expectedErrors: Errors{},
|
||||
},
|
||||
{
|
||||
description: "pointer form with invalid data",
|
||||
data: PointerForm{
|
||||
URL: alphaDashStr,
|
||||
URLPointer: &alphaDashStr,
|
||||
AlphaDash: urlStr,
|
||||
AlphaDashPointer: &urlStr,
|
||||
},
|
||||
expectedErrors: Errors{
|
||||
Error{
|
||||
FieldNames: []string{"Url", "UrlPointer"},
|
||||
Classification: "Url",
|
||||
Message: "Url",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"UrlPointer"},
|
||||
Classification: "Url",
|
||||
Message: "Url",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"AlphaDash"},
|
||||
Classification: "AlphaDash",
|
||||
Message: "AlphaDash",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"AlphaDashPointer"},
|
||||
Classification: "AlphaDash",
|
||||
Message: "AlphaDash",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "errors with required fields",
|
||||
data: []*struct {
|
||||
AlphaDash string `binding:"Required;AlphaDash"`
|
||||
AlphaDashDot string `binding:"Required;AlphaDashDot"`
|
||||
Size string `binding:"Required;Size(1)"`
|
||||
SizeSlice []string `binding:"Required;Size(1)"`
|
||||
MinSize string `binding:"Required;MinSize(5)"`
|
||||
MinSizeSlice []string `binding:"Required;MinSize(5)"`
|
||||
MaxSize string `binding:"Required;MaxSize(1)"`
|
||||
MaxSizeSlice []string `binding:"Required;MaxSize(1)"`
|
||||
Range int `binding:"Required;Range(1,2)"`
|
||||
Email string `binding:"Required;Email"`
|
||||
URL string `binding:"Required;Url"`
|
||||
In string `binding:"Required;Default(0);In(1,2,3)"`
|
||||
NotIn string `binding:"Required;NotIn(1,2,3)"`
|
||||
}{
|
||||
{},
|
||||
},
|
||||
expectedErrors: Errors{
|
||||
Error{
|
||||
FieldNames: []string{"AlphaDash"},
|
||||
Classification: "Required",
|
||||
Message: "Required",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"AlphaDashDot"},
|
||||
Classification: "Required",
|
||||
Message: "Required",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"Size"},
|
||||
Classification: "Required",
|
||||
Message: "Required",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"SizeSlice"},
|
||||
Classification: "Required",
|
||||
Message: "Required",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"MinSize"},
|
||||
Classification: "Required",
|
||||
Message: "Required",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"MinSizeSlice"},
|
||||
Classification: "Required",
|
||||
Message: "Required",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"MaxSize"},
|
||||
Classification: "Required",
|
||||
Message: "Required",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"MaxSizeSlice"},
|
||||
Classification: "Required",
|
||||
Message: "Required",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"Range"},
|
||||
Classification: "Required",
|
||||
Message: "Required",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"Email"},
|
||||
Classification: "Required",
|
||||
Message: "Required",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"Url"},
|
||||
Classification: "Required",
|
||||
Message: "Required",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"In"},
|
||||
Classification: "Required",
|
||||
Message: "Required",
|
||||
},
|
||||
Error{
|
||||
FieldNames: []string{"NotIn"},
|
||||
Classification: "Required",
|
||||
Message: "Required",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func Test_Validation(t *testing.T) {
|
||||
for _, testCase := range validationTestCases {
|
||||
performValidationTest(t, testCase)
|
||||
}
|
||||
}
|
||||
|
||||
func performValidationTest(t *testing.T, testCase validationTestCase) {
|
||||
httpRecorder := httptest.NewRecorder()
|
||||
m := chi.NewRouter()
|
||||
|
||||
m.Post(testRoute, func(_ http.ResponseWriter, req *http.Request) {
|
||||
actual := Validate(req, testCase.data)
|
||||
assert.EqualValues(t, fmt.Sprintf("%+v", testCase.expectedErrors), fmt.Sprintf("%+v", actual), testCase.description)
|
||||
})
|
||||
|
||||
req, err := http.NewRequest("POST", testRoute, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
m.ServeHTTP(httpRecorder, req)
|
||||
|
||||
switch httpRecorder.Code {
|
||||
case http.StatusNotFound:
|
||||
panic("Routing is messed up in test fixture (got 404): check methods and paths")
|
||||
case http.StatusInternalServerError:
|
||||
panic("Something bad happened on '" + testCase.description + "'")
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
validationTestCase struct {
|
||||
description string
|
||||
data any
|
||||
expectedErrors Errors
|
||||
}
|
||||
)
|
Loading…
Add table
Add a link
Reference in a new issue