Skip to content

Commit

Permalink
unit test and readme
Browse files Browse the repository at this point in the history
  • Loading branch information
Rhyanz46 committed Sep 6, 2024
1 parent fc39525 commit 2ca1d60
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 513 deletions.
215 changes: 125 additions & 90 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ go get github.com/Rhyanz46/go-map-validator/map_validator
```

### discussion or updates

- [On Telegram](https://t.me/addlist/Wi84VFNkvz85MWFl)

## Features
Expand All @@ -19,9 +20,9 @@ go get github.com/Rhyanz46/go-map-validator/map_validator
- validate data from `http.Request` json/multipart
- support file upload
- Unique Value
- ex case : `old_password` and `new_password` cant be using same value
- ex case : `old_password` and `new_password` cant be using same value
- RequiredWithout check
- ex case : the field `flavor` is required if `custom_flavor` is null
- ex case : the field `flavor` is required if `custom_flavor` is null
- enum value check
- min/max length data check
- email field check
Expand All @@ -30,7 +31,8 @@ go get github.com/Rhyanz46/go-map-validator/map_validator
- IPv4 Network check
- regex on string validation
- nested validation 🔥
- you can create your own extension 🔥🔥🔥🔥 (example : [https://github.com/Rhyanz46/go-map-validator/example_extensions/](https://github.com/Rhyanz46/go-map-validator/tree/main/example_extensions))
- you can create your own extension 🔥🔥🔥🔥 (
example : [https://github.com/Rhyanz46/go-map-validator/example_extensions/](https://github.com/Rhyanz46/go-map-validator/tree/main/example_extensions))
- custom message :
- on invalid regex message : ✅ ready
- on type not match message : ✅ ready
Expand All @@ -55,7 +57,6 @@ go get github.com/Rhyanz46/go-map-validator/map_validator
| 5 | `${expected_min_length}` |
| 6 | `${expected_max_length}` |


## Road Map

- get from urls params http
Expand All @@ -65,191 +66,225 @@ go get github.com/Rhyanz46/go-map-validator/map_validator
- image resolution validation
- multi validation on one field (ex : IPv4: true, UUID: true)


## example :

### Example 1

```go
payload := map[string]interface{}{"jenis_kelamin": "laki-laki", "hoby": "Main PS", "umur": 1, "menikah": true}
err := map_validator.NewValidateBuilder().SetRules(map_validator.RulesWrapper{
Rules: map[string]map_validator.Rules{
"jenis_kelamin": {Enum: &map_validator.EnumField[any]{Items: []string{"laki-laki", "perempuan"}}},
"hoby": {Type: reflect.String, Null: false},
"menikah": {Type: reflect.Bool, Null: false},
},
},
Rules: map[string]map_validator.Rules{
"jenis_kelamin": {Enum: &map_validator.EnumField[any]{Items: []string{"laki-laki", "perempuan"}}},
"hoby": {Type: reflect.String, Null: false},
"menikah": {Type: reflect.Bool, Null: false},
},
},
).Load(payload).RunValidate()
if err != nil {
t.Errorf("Expected not have error, but got error : %s", err)
t.Errorf("Expected not have error, but got error : %s", err)
}

err = map_validator.NewValidateBuilder().SetRules(map_validator.RulesWrapper{
Rules: map[string]map_validator.Rules{
"jenis_kelamin": {Enum: &map_validator.EnumField[any]{Items: []string{"laki-laki", "perempuan"}}},
"hoby": {Type: reflect.Int, Null: false},
"menikah": {Type: reflect.Bool, Null: false},
},
},
Rules: map[string]map_validator.Rules{
"jenis_kelamin": {Enum: &map_validator.EnumField[any]{Items: []string{"laki-laki", "perempuan"}}},
"hoby": {Type: reflect.Int, Null: false},
"menikah": {Type: reflect.Bool, Null: false},
},
},
).Load(payload).RunValidate()
if err == nil {
t.Error("Expected have an error, but you got no error")
t.Error("Expected have an error, but you got no error")
}
```

### Example 2 ( Nested Object Validation )

```go
filterRole := map[string]map_validator.Rules{
"search": {Type: reflect.String, Null: true},
"organization_id": {UUID: true, Null: true},
"search": {Type: reflect.String, Null: true},
"organization_id": {UUID: true, Null: true},
}
jsonDataRoles := map_validator.NewValidateBuilder().StrictKeys().SetRules(map_validator.RulesWrapper{
Rules: map[string]map_validator.Rules{
"filter": {Object: &filterRole, Null: true},
"rows_per_page": {Type: reflect.Int64, Null: true},
"page_index": {Type: reflect.Int64, Null: true},
"sort": {
Null: true,
IfNull: "FULL_NAME:DESC",
Type: reflect.String, Enum: &map_validator.EnumField[any]{
Items: []string{"FULL_NAME:DESC", "FULL_NAME:ASC", "EMAIL:ASC", "EMAIL:DESC"},
},
},
Rules: map[string]map_validator.Rules{
"filter": {Object: &filterRole, Null: true},
"rows_per_page": {Type: reflect.Int64, Null: true},
"page_index": {Type: reflect.Int64, Null: true},
"sort": {
Null: true,
IfNull: "FULL_NAME:DESC",
Type: reflect.String, Enum: &map_validator.EnumField[any]{
Items: []string{"FULL_NAME:DESC", "FULL_NAME:ASC", "EMAIL:ASC", "EMAIL:DESC"},
},
},
}
})
```
![image](https://github.com/Rhyanz46/go-map-validator/assets/24217568/9f58dde4-b175-4a4f-9369-fa0974c25942)

![image](https://github.com/Rhyanz46/go-map-validator/assets/24217568/9f58dde4-b175-4a4f-9369-fa0974c25942)

### Example 3 ( Echo Framework )

```go
func handleLogin(c echo.Context) error {
jsonHttp, err := map_validator.NewValidateBuilder().SetRules(map_validator.RulesWrapper{
Rules: map[string]map_validator.Rules{
"email": {Email: true, Max: map_validator.SetTotal(100)},
"password": {Type: reflect.String, Min: map_validator.SetTotal(6), Max: map_validator.SetTotal(30)},
},
}).LoadJsonHttp(c.Request())
if err != nil {
return c.JSON(http.StatusBadRequest, err)
}
err = jsonHttp.RunValidate()
if err != nil {
return c.JSON(http.StatusBadRequest, err)
}
return c.NoContent(http.StatusOK)
jsonHttp, err := map_validator.NewValidateBuilder().SetRules(map_validator.RulesWrapper{
Rules: map[string]map_validator.Rules{
"email": {Email: true, Max: map_validator.SetTotal(100)},
"password": {Type: reflect.String, Min: map_validator.SetTotal(6), Max: map_validator.SetTotal(30)},
},
}).LoadJsonHttp(c.Request())
if err != nil {
return c.JSON(http.StatusBadRequest, err)
}
err = jsonHttp.RunValidate()
if err != nil {
return c.JSON(http.StatusBadRequest, err)
}
return c.NoContent(http.StatusOK)
}

func main() {
e := echo.New()
e.POST("/login", handleLogin)
e.Start(":3000")
e := echo.New()
e.POST("/login", handleLogin)
e.Start(":3000")
}

```

### Example 4 ( Bind To Struct )

```go
type Data struct {
JK string `map_validator:"jenis_kelamin"`
Hoby string `map_validator:"hoby"`
Menikah bool `map_validator:"menikah"`
JK string `map_validator:"jenis_kelamin"`
Hoby string `map_validator:"hoby"`
Menikah bool `map_validator:"menikah"`
}

payload := map[string]interface{}{"jenis_kelamin": "laki-laki", "hoby": "Main PS", "umur": 1, "menikah": true}
err := map_validator.NewValidateBuilder().SetRules(map_validator.RulesWrapper{
Rules: map[string]map_validator.Rules{
"jenis_kelamin": {Enum: &map_validator.EnumField[any]{Items: []string{"laki-laki", "perempuan"}}},
"hoby": {Type: reflect.String, Null: false},
"menikah": {Type: reflect.Bool, Null: false},
},
Rules: map[string]map_validator.Rules{
"jenis_kelamin": {Enum: &map_validator.EnumField[any]{Items: []string{"laki-laki", "perempuan"}}},
"hoby": {Type: reflect.String, Null: false},
"menikah": {Type: reflect.Bool, Null: false},
},
}).Load(payload).RunValidate()
if err != nil {
t.Errorf("Expected not have error, but got error : %s", err)
t.Errorf("Expected not have error, but got error : %s", err)
}

testBind := &Data{}
if testBind.JK != "" {
t.Errorf("Expected : '' But you got : %s", testBind.JK)
t.Errorf("Expected : '' But you got : %s", testBind.JK)
}
err = extraCheck.Bind(testBind)
if err != nil {
t.Errorf("Error : %s ", err)
t.Errorf("Error : %s ", err)
}

if testBind.JK != payload["jenis_kelamin"] {
t.Errorf("Expected : %s But you got : %s", payload["jenis_kelamin"], testBind.JK)
t.Errorf("Expected : %s But you got : %s", payload["jenis_kelamin"], testBind.JK)
}

```


### Example 5 ( Custom message )

```go
payload := map[string]interface{}{"total": 12, "unit": "KG"}
validRole := map_validator.RulesWrapper{
Rules: map[string]map_validator.Rules{
"total": {
Type: reflect.Int,
CustomMsg: map_validator.CustomMsg{
OnTypeNotMatch: map_validator.SetMessage("Total must be a number, but your input is ${actual_type}"),
},
},
},
Rules: map[string]map_validator.Rules{
"total": {
Type: reflect.Int,
CustomMsg: map_validator.CustomMsg{
OnTypeNotMatch: map_validator.SetMessage("Total must be a number, but your input is ${actual_type}"),
},
},
},
}

check, err := map_validator.NewValidateBuilder().SetRules(validRole).Load(payload)
if err != nil {
t.Errorf("Expected not have error, but got error : %s", err)
t.Errorf("Expected not have error, but got error : %s", err)
}
_, err = check.RunValidate()
if err != nil {
t.Errorf("Expected not have error, but got error : %s", err)
t.Errorf("Expected not have error, but got error : %s", err)
}

```


### Example 6 ( Regex validator )

```go
payload := map[string]interface{}{"hp": "+62567888", "email": "[email protected]"}
validRole := map_validator.RulesWrapper{
Rules: map[string]map_validator.Rules{
"hp": {RegexString: `^\+(?:\d{2}[- ]?\d{6}|\d{11})$`},
"email": {RegexString: `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`},
},
Rules: map[string]map_validator.Rules{
"hp": {RegexString: `^\+(?:\d{2}[- ]?\d{6}|\d{11})$`},
"email": {RegexString: `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`},
},
}
check, err := map_validator.NewValidateBuilder().SetRules(validRole).Load(payload)
if err != nil {
t.Errorf("Expected not have error, but got error : %s", err)
t.Errorf("Expected not have error, but got error : %s", err)
}
_, err = check.RunValidate()
if err != nil {
t.Errorf("Expected not have error, but got error : %s", err)
t.Errorf("Expected not have error, but got error : %s", err)
}

```


### Example 7 ( Unique value )

```go
role := map_validator.RulesWrapper{
Rules: map[string]map_validator.Rules{
"password": {Type: reflect.String, Unique: []string{"password"}, Null: true},
"new_password": {Type: reflect.String, Unique: []string{"password"}, Null: true},
},
Rules: map[string]map_validator.Rules{
"password": {Type: reflect.String, Unique: []string{"password"}, Null: true},
"new_password": {Type: reflect.String, Unique: []string{"password"}, Null: true},
},
}
payload := map[string]interface{}{
"password": "sabalong",
"new_password": "sabalong",
"password": "sabalong",
"new_password": "sabalong",
}
check, err := map_validator.NewValidateBuilder().SetRules(role).Load(payload)
if err != nil {
t.Errorf("Expected not have error, but got error : %s", err)
return
t.Errorf("Expected not have error, but got error : %s", err)
return
}
expected := "value of 'password' and 'new_password' fields must be different"
_, err = check.RunValidate()
if err.Error() != expected {
t.Errorf("Expected :%s. But you got : %s", expected, err)
t.Errorf("Expected :%s. But you got : %s", expected, err)
}
```

### Example 8 ( Manipulator )

```go
data := map[string]interface{}{
"description": "test arian keren bgt kan \n\n mantap bukan",
"note": "coba aja mungkin bisa \t mantap",
}

trimAfterValidation := func (i interface{}) (result interface{}, e error) {
x := i.(string)
result = trimAndClean(x)
return
}

roles := map_validator.BuildRoles().
SetRule("description", map_validator.Rules{Type: reflect.String}).
SetRule("note", map_validator.Rules{Type: reflect.String}).
SetManipulator("description", &trimAfterValidation).
Done()

xx, err := map_validator.NewValidateBuilder().SetRules(roles).Load(data)
extraCheck, err := xx.RunValidate()
if err != nil {
t.Errorf("Expected not have error, but got error : %s", err)
return
}
if extraCheck.GetData()["description"] != "test arian keren bgt kan mantap bukan" {
t.Errorf("Expected description to be test arian keren bgt kan mantap bukan, but got %s", data["description"])
}
```
Loading

0 comments on commit 2ca1d60

Please sign in to comment.