@@ -14753,3 +14753,223 @@ func TestOmitZeroWithMaps(t *testing.T) {
1475314753 Equal (t , err2 , nil ) // No error
1475414754 })
1475514755}
14756+ func TestRequiredIfWithNilBytesSlice (t * testing.T ) {
14757+ // Tests the behavior of required_if with nil byte slices
14758+ type TextOrBytes struct {
14759+ Text string `validate:"required_if=Bytes nil"`
14760+ Bytes []byte `validate:"required_if=Text nil"`
14761+ }
14762+
14763+ validate := New (WithRequiredStructEnabled ())
14764+
14765+ t .Run ("Text empty, Bytes empty but not nil" , func (t * testing.T ) {
14766+ // Test 1: Text empty, Bytes empty but not nil
14767+ obj := TextOrBytes {
14768+ Text : "" ,
14769+ Bytes : []byte {},
14770+ }
14771+ err := validate .Struct (obj )
14772+
14773+ Equal (t , err , nil ) // No error - Bytes is not nil, just empty
14774+ })
14775+
14776+ t .Run ("Text empty, Bytes nil" , func (t * testing.T ) {
14777+ // Test 2: Text empty, Bytes nil
14778+ obj := TextOrBytes {
14779+ Text : "" ,
14780+ Bytes : nil ,
14781+ }
14782+ err := validate .Struct (obj )
14783+
14784+ NotEqual (t , err , nil ) // Error - Text is required when Bytes is nil
14785+ })
14786+
14787+ t .Run ("Text populated, Bytes nil" , func (t * testing.T ) {
14788+ // Test 3: Text populated, Bytes nil
14789+ obj := TextOrBytes {
14790+ Text : "Hello" ,
14791+ Bytes : nil ,
14792+ }
14793+ err := validate .Struct (obj )
14794+
14795+ Equal (t , err , nil ) // No error - Text has value when Bytes is nil
14796+ })
14797+
14798+ t .Run ("Text populated, Bytes empty but not nil" , func (t * testing.T ) {
14799+ // Test 4: Text populated, Bytes empty but not nil
14800+ obj := TextOrBytes {
14801+ Text : "Hello" ,
14802+ Bytes : []byte {},
14803+ }
14804+ err := validate .Struct (obj )
14805+
14806+ Equal (t , err , nil ) // No error - Neither field is nil
14807+ })
14808+
14809+ t .Run ("Text empty, Bytes populated" , func (t * testing.T ) {
14810+ // Test 5: Text empty, Bytes populated
14811+ obj := TextOrBytes {
14812+ Text : "" ,
14813+ Bytes : []byte ("World" ),
14814+ }
14815+ err := validate .Struct (obj )
14816+
14817+ Equal (t , err , nil ) // No error - Bytes has value when Text is empty
14818+ })
14819+
14820+ t .Run ("Both fields populated" , func (t * testing.T ) {
14821+ // Test 6: Both fields populated
14822+ obj := TextOrBytes {
14823+ Text : "Hello" ,
14824+ Bytes : []byte ("World" ),
14825+ }
14826+ err := validate .Struct (obj )
14827+
14828+ Equal (t , err , nil ) // No error - Both fields have values
14829+ })
14830+ }
14831+ func TestRequiredIfWithMaps (t * testing.T ) {
14832+ // Tests the behavior of required_if with maps
14833+ type TextOrMap struct {
14834+ Text string `validate:"required_if=Data nil"`
14835+ Data map [string ]interface {} `validate:"required_if=Text nil"`
14836+ }
14837+
14838+ validate := New (WithRequiredStructEnabled ())
14839+
14840+ t .Run ("Text empty, Map nil" , func (t * testing.T ) {
14841+ // Test 1: Text empty, Map nil
14842+ obj := TextOrMap {
14843+ Text : "" ,
14844+ Data : nil ,
14845+ }
14846+ err := validate .Struct (obj )
14847+
14848+ NotEqual (t , err , nil ) // Error - Text is required when Data is nil
14849+ })
14850+
14851+ t .Run ("Text populated, Map nil" , func (t * testing.T ) {
14852+ // Test 2: Text populated, Map nil
14853+ obj := TextOrMap {
14854+ Text : "Hello" ,
14855+ Data : nil ,
14856+ }
14857+ err := validate .Struct (obj )
14858+
14859+ Equal (t , err , nil ) // No error - Text has value when Data is nil
14860+ })
14861+
14862+ t .Run ("Text empty, Map empty but not nil" , func (t * testing.T ) {
14863+ // Test 3: Text empty, Map empty but not nil
14864+ obj := TextOrMap {
14865+ Text : "" ,
14866+ Data : map [string ]interface {}{},
14867+ }
14868+ err := validate .Struct (obj )
14869+
14870+ Equal (t , err , nil ) // No error - Data is not nil, just empty
14871+ })
14872+
14873+ t .Run ("Text populated, Map empty but not nil" , func (t * testing.T ) {
14874+ // Test 4: Text populated, Map empty but not nil
14875+ obj := TextOrMap {
14876+ Text : "Hello" ,
14877+ Data : map [string ]interface {}{},
14878+ }
14879+ err := validate .Struct (obj )
14880+
14881+ Equal (t , err , nil ) // No error - Neither field is nil
14882+ })
14883+
14884+ t .Run ("Text empty, Map populated" , func (t * testing.T ) {
14885+ // Test 5: Text empty, Map populated
14886+ obj := TextOrMap {
14887+ Text : "" ,
14888+ Data : map [string ]interface {}{"key" : "value" },
14889+ }
14890+ err := validate .Struct (obj )
14891+
14892+ Equal (t , err , nil ) // No error - Data has value when Text is empty
14893+ })
14894+
14895+ t .Run ("Both fields populated" , func (t * testing.T ) {
14896+ // Test 6: Both fields populated
14897+ obj := TextOrMap {
14898+ Text : "Hello" ,
14899+ Data : map [string ]interface {}{"key" : "value" },
14900+ }
14901+ err := validate .Struct (obj )
14902+
14903+ Equal (t , err , nil ) // No error - Both fields have values
14904+ })
14905+ }
14906+ func TestRequiredIfWithArrays (t * testing.T ) {
14907+ // Tests the behavior of required_if with arrays
14908+ type TextOrArray struct {
14909+ Text string `validate:"required_if=Data 3"` // Check if array length is 3
14910+ Data [3 ]string `validate:"required_if=Text nil"` // Check if Text is empty
14911+ }
14912+
14913+ // Also test with a different length to verify behavior
14914+ type TextOrSmallArray struct {
14915+ Text string `validate:"required_if=Data 2"` // Check if array length is 2 (which it never will be for [3]string)
14916+ Data [3 ]string `validate:"required_if=Text nil"` // Check if Text is empty
14917+ }
14918+
14919+ validate := New (WithRequiredStructEnabled ())
14920+
14921+ t .Run ("Array length always matches declared size" , func (t * testing.T ) {
14922+ // Test 1: Text empty, Array has length 3
14923+ obj := TextOrArray {
14924+ Text : "" ,
14925+ Data : [3 ]string {}, // Zero values but length is 3
14926+ }
14927+ err := validate .Struct (obj )
14928+
14929+ NotEqual (t , err , nil ) // Error - Text is required when Data length equals 3
14930+ })
14931+
14932+ t .Run ("Text populated, Array always has declared length" , func (t * testing.T ) {
14933+ // Test 2: Text populated, Array has length 3
14934+ obj := TextOrArray {
14935+ Text : "Hello" ,
14936+ Data : [3 ]string {},
14937+ }
14938+ err := validate .Struct (obj )
14939+
14940+ Equal (t , err , nil ) // No error - Text has value
14941+ })
14942+
14943+ t .Run ("Length check that never matches doesn't trigger validation" , func (t * testing.T ) {
14944+ // Test 3: Text empty, Array has length 3 but we check for length 2
14945+ obj := TextOrSmallArray {
14946+ Text : "" ,
14947+ Data : [3 ]string {},
14948+ }
14949+ err := validate .Struct (obj )
14950+
14951+ Equal (t , err , nil ) // No error - Data length never equals 2
14952+ })
14953+
14954+ t .Run ("Array values don't affect length check" , func (t * testing.T ) {
14955+ // Test 4: Text empty, Array partially populated but still length 3
14956+ obj := TextOrArray {
14957+ Text : "" ,
14958+ Data : [3 ]string {"One" , "Two" , "" },
14959+ }
14960+ err := validate .Struct (obj )
14961+
14962+ NotEqual (t , err , nil ) // Error - Text is required when Data length equals 3
14963+ })
14964+
14965+ t .Run ("Array values with Text populated passes validation" , func (t * testing.T ) {
14966+ // Test 5: Text populated, Array with values
14967+ obj := TextOrArray {
14968+ Text : "Hello" ,
14969+ Data : [3 ]string {"One" , "Two" , "Three" },
14970+ }
14971+ err := validate .Struct (obj )
14972+
14973+ Equal (t , err , nil ) // No error - Text has value
14974+ })
14975+ }
0 commit comments