|
| 1 | +package validation |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "testing" |
| 6 | + |
| 7 | + "github.com/stretchr/testify/assert" |
| 8 | +) |
| 9 | + |
| 10 | +func TestMap(t *testing.T) { |
| 11 | + var m0 map[string]interface{} |
| 12 | + m1 := map[string]interface{}{"A": "abc", "B": "xyz", "c": "abc", "D": (*string)(nil), "F": (*String123)(nil), "H": []string{"abc", "abc"}, "I": map[string]string{"foo": "abc"}} |
| 13 | + m2 := map[string]interface{}{"E": String123("xyz"), "F": (*String123)(nil)} |
| 14 | + m3 := map[string]interface{}{"M3": Model3{}} |
| 15 | + m4 := map[string]interface{}{"M3": Model3{A: "abc"}} |
| 16 | + m5 := map[string]interface{}{"A": "internal", "B": ""} |
| 17 | + m6 := map[int]string{11: "abc", 22: "xyz"} |
| 18 | + tests := []struct { |
| 19 | + tag string |
| 20 | + model interface{} |
| 21 | + rules []*KeyRules |
| 22 | + err string |
| 23 | + }{ |
| 24 | + // empty rules |
| 25 | + {"t1.1", m1, []*KeyRules{}, ""}, |
| 26 | + {"t1.2", m1, []*KeyRules{Key("A"), Key("B")}, ""}, |
| 27 | + // normal rules |
| 28 | + {"t2.1", m1, []*KeyRules{Key("A", &validateAbc{}), Key("B", &validateXyz{})}, ""}, |
| 29 | + {"t2.2", m1, []*KeyRules{Key("A", &validateXyz{}), Key("B", &validateAbc{})}, "A: error xyz; B: error abc."}, |
| 30 | + {"t2.3", m1, []*KeyRules{Key("A", &validateXyz{}), Key("c", &validateXyz{})}, "A: error xyz; c: error xyz."}, |
| 31 | + {"t2.4", m1, []*KeyRules{Key("D", Length(0, 5))}, ""}, |
| 32 | + {"t2.5", m1, []*KeyRules{Key("F", Length(0, 5))}, ""}, |
| 33 | + {"t2.6", m1, []*KeyRules{Key("H", Each(&validateAbc{})), Key("I", Each(&validateAbc{}))}, ""}, |
| 34 | + {"t2.7", m1, []*KeyRules{Key("H", Each(&validateXyz{})), Key("I", Each(&validateXyz{}))}, "H: (0: error xyz; 1: error xyz.); I: (foo: error xyz.)."}, |
| 35 | + {"t2.8", m1, []*KeyRules{Key("I", Map(Key("foo", &validateAbc{})))}, ""}, |
| 36 | + {"t2.9", m1, []*KeyRules{Key("I", Map(Key("foo", &validateXyz{})))}, "I: (foo: error xyz.)."}, |
| 37 | + // non-map value |
| 38 | + {"t3.1", &m1, []*KeyRules{}, ""}, |
| 39 | + {"t3.2", nil, []*KeyRules{}, ErrNotMap.Error()}, |
| 40 | + {"t3.3", m0, []*KeyRules{}, ""}, |
| 41 | + {"t3.4", &m0, []*KeyRules{}, ""}, |
| 42 | + {"t3.5", 123, []*KeyRules{}, ErrNotMap.Error()}, |
| 43 | + // invalid key spec |
| 44 | + {"t4.1", m1, []*KeyRules{Key(123)}, "123: key not the correct type."}, |
| 45 | + {"t4.2", m1, []*KeyRules{Key("X")}, "X: required key is missing."}, |
| 46 | + {"t4.3", m1, []*KeyRules{Key("X").Optional()}, ""}, |
| 47 | + // non-string keys |
| 48 | + {"t5.1", m6, []*KeyRules{Key(11, &validateAbc{}), Key(22, &validateXyz{})}, ""}, |
| 49 | + {"t5.2", m6, []*KeyRules{Key(11, &validateXyz{}), Key(22, &validateAbc{})}, "11: error xyz; 22: error abc."}, |
| 50 | + // validatable value |
| 51 | + {"t6.1", m2, []*KeyRules{Key("E")}, "E: error 123."}, |
| 52 | + {"t6.2", m2, []*KeyRules{Key("E", Skip)}, ""}, |
| 53 | + {"t6.3", m2, []*KeyRules{Key("E", Skip.When(true))}, ""}, |
| 54 | + {"t6.4", m2, []*KeyRules{Key("E", Skip.When(false))}, "E: error 123."}, |
| 55 | + // Required, NotNil |
| 56 | + {"t7.1", m2, []*KeyRules{Key("F", Required)}, "F: cannot be blank."}, |
| 57 | + {"t7.2", m2, []*KeyRules{Key("F", NotNil)}, "F: is required."}, |
| 58 | + {"t7.3", m2, []*KeyRules{Key("F", Skip, Required)}, ""}, |
| 59 | + {"t7.4", m2, []*KeyRules{Key("F", Skip, NotNil)}, ""}, |
| 60 | + {"t7.5", m2, []*KeyRules{Key("F", Skip.When(true), Required)}, ""}, |
| 61 | + {"t7.6", m2, []*KeyRules{Key("F", Skip.When(true), NotNil)}, ""}, |
| 62 | + {"t7.7", m2, []*KeyRules{Key("F", Skip.When(false), Required)}, "F: cannot be blank."}, |
| 63 | + {"t7.8", m2, []*KeyRules{Key("F", Skip.When(false), NotNil)}, "F: is required."}, |
| 64 | + // validatable structs |
| 65 | + {"t8.1", m3, []*KeyRules{Key("M3", Skip)}, ""}, |
| 66 | + {"t8.2", m3, []*KeyRules{Key("M3")}, "M3: (A: error abc.)."}, |
| 67 | + {"t8.3", m4, []*KeyRules{Key("M3")}, ""}, |
| 68 | + // internal error |
| 69 | + {"t9.1", m5, []*KeyRules{Key("A", &validateAbc{}), Key("B", Required), Key("A", &validateInternalError{})}, "error internal"}, |
| 70 | + } |
| 71 | + for _, test := range tests { |
| 72 | + err1 := Validate(test.model, Map(test.rules...).AllowExtraKeys()) |
| 73 | + err2 := ValidateWithContext(context.Background(), test.model, Map(test.rules...).AllowExtraKeys()) |
| 74 | + assertError(t, test.err, err1, test.tag) |
| 75 | + assertError(t, test.err, err2, test.tag) |
| 76 | + } |
| 77 | + |
| 78 | + a := map[string]interface{}{"Name": "name", "Value": "demo", "Extra": true} |
| 79 | + err := Validate(a, Map( |
| 80 | + Key("Name", Required), |
| 81 | + Key("Value", Required, Length(5, 10)), |
| 82 | + )) |
| 83 | + assert.EqualError(t, err, "Extra: key not expected; Value: the length must be between 5 and 10.") |
| 84 | +} |
| 85 | + |
| 86 | +func TestMapWithContext(t *testing.T) { |
| 87 | + m1 := map[string]interface{}{"A": "abc", "B": "xyz", "c": "abc", "g": "xyz"} |
| 88 | + m2 := map[string]interface{}{"A": "internal", "B": ""} |
| 89 | + tests := []struct { |
| 90 | + tag string |
| 91 | + model interface{} |
| 92 | + rules []*KeyRules |
| 93 | + err string |
| 94 | + }{ |
| 95 | + // normal rules |
| 96 | + {"t1.1", m1, []*KeyRules{Key("A", &validateContextAbc{}), Key("B", &validateContextXyz{})}, ""}, |
| 97 | + {"t1.2", m1, []*KeyRules{Key("A", &validateContextXyz{}), Key("B", &validateContextAbc{})}, "A: error xyz; B: error abc."}, |
| 98 | + {"t1.3", m1, []*KeyRules{Key("A", &validateContextXyz{}), Key("c", &validateContextXyz{})}, "A: error xyz; c: error xyz."}, |
| 99 | + {"t1.4", m1, []*KeyRules{Key("g", &validateContextAbc{})}, "g: error abc."}, |
| 100 | + // skip rule |
| 101 | + {"t2.1", m1, []*KeyRules{Key("g", Skip, &validateContextAbc{})}, ""}, |
| 102 | + {"t2.2", m1, []*KeyRules{Key("g", &validateContextAbc{}, Skip)}, "g: error abc."}, |
| 103 | + // internal error |
| 104 | + {"t3.1", m2, []*KeyRules{Key("A", &validateContextAbc{}), Key("B", Required), Key("A", &validateInternalError{})}, "error internal"}, |
| 105 | + } |
| 106 | + for _, test := range tests { |
| 107 | + err := ValidateWithContext(context.Background(), test.model, Map(test.rules...).AllowExtraKeys()) |
| 108 | + assertError(t, test.err, err, test.tag) |
| 109 | + } |
| 110 | + |
| 111 | + a := map[string]interface{}{"Name": "name", "Value": "demo", "Extra": true} |
| 112 | + err := ValidateWithContext(context.Background(), a, Map( |
| 113 | + Key("Name", Required), |
| 114 | + Key("Value", Required, Length(5, 10)), |
| 115 | + )) |
| 116 | + if assert.NotNil(t, err) { |
| 117 | + assert.Equal(t, "Extra: key not expected; Value: the length must be between 5 and 10.", err.Error()) |
| 118 | + } |
| 119 | +} |
0 commit comments