Skip to content

Commit

Permalink
Add Array.IsValueEqual and Array.NotValueEqual (#287)
Browse files Browse the repository at this point in the history
Co-authored-by: Victor Gaydov <[email protected]>
  • Loading branch information
nhAnik and gavv authored Feb 9, 2023
1 parent 1f66a3a commit b3490ba
Show file tree
Hide file tree
Showing 2 changed files with 251 additions and 0 deletions.
108 changes: 108 additions & 0 deletions array.go
Original file line number Diff line number Diff line change
Expand Up @@ -1452,6 +1452,114 @@ func (a *Array) NotContainsOnly(values ...interface{}) *Array {
return a
}

// IsValueEqual succeeds if array's value at the given index is equal to given value.
//
// Before comparison, both values are converted to canonical form. value should be
// map[string]interface{} or struct.
//
// Example:
//
// array := NewArray(t, []interface{}{"foo", "123"})
// array.IsValueEqual(1, 123)
func (a *Array) IsValueEqual(index int, value interface{}) *Array {
opChain := a.chain.enter("IsValueEqual(%d)", index)
defer opChain.leave()

if opChain.failed() {
return a
}

if index < 0 || index >= len(a.value) {
opChain.fail(AssertionFailure{
Type: AssertInRange,
Actual: &AssertionValue{index},
Expected: &AssertionValue{AssertionRange{
Min: 0,
Max: len(a.value) - 1,
}},
Errors: []error{
errors.New("expected: valid element index"),
},
})
return a
}

expected, ok := canonValue(opChain, value)
if !ok {
return a
}

if !reflect.DeepEqual(expected, a.value[index]) {
opChain.fail(AssertionFailure{
Type: AssertEqual,
Actual: &AssertionValue{a.value[index]},
Expected: &AssertionValue{value},
Errors: []error{
fmt.Errorf(
"expected: array value at index %d is equal to given value",
index),
},
})
return a
}

return a
}

// NotValueEqual succeeds if array's value at the given index is not equal to given value.
//
// Before comparison, both values are converted to canonical form. value should be
// map[string]interface{} or struct.
//
// Example:
//
// array := NewArray(t, []interface{}{"foo", "123"})
// array.NotValueEqual(1, 234)
func (a *Array) NotValueEqual(index int, value interface{}) *Array {
opChain := a.chain.enter("NotValueEqual(%d)", index)
defer opChain.leave()

if opChain.failed() {
return a
}

if index < 0 || index >= len(a.value) {
opChain.fail(AssertionFailure{
Type: AssertInRange,
Actual: &AssertionValue{index},
Expected: &AssertionValue{AssertionRange{
Min: 0,
Max: len(a.value) - 1,
}},
Errors: []error{
errors.New("expected: valid element index"),
},
})
return a
}

expected, ok := canonValue(opChain, value)
if !ok {
return a
}

if reflect.DeepEqual(expected, a.value[index]) {
opChain.fail(AssertionFailure{
Type: AssertNotEqual,
Actual: &AssertionValue{a.value[index]},
Expected: &AssertionValue{value},
Errors: []error{
fmt.Errorf(
"expected: array value at index %d is not equal to given value",
index),
},
})
return a
}

return a
}

// IsOrdered succeeds if every element is not less than the previous element
// as defined on the given `less` comparator function.
// For default, it will use built-in comparator function for each data type.
Expand Down
143 changes: 143 additions & 0 deletions array_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ func TestArray_FailedChain(t *testing.T) {
value.NotContainsAny("foo")
value.ContainsOnly("foo")
value.NotContainsOnly("foo")
value.IsValueEqual(0, nil)
value.NotValueEqual(0, nil)

assert.NotNil(t, value.Iter())
assert.Equal(t, 0, len(value.Iter()))
Expand Down Expand Up @@ -1817,6 +1819,147 @@ func TestArray_NotOrdered(t *testing.T) {
}
}

func TestArray_ValueEqual(t *testing.T) {
reporter := newMockReporter(t)

array := NewArray(reporter, []interface{}{
123,
[]interface{}{"456", 789},
map[string]interface{}{
"a": "b",
},
})

array.IsValueEqual(0, 123)
array.chain.assertNotFailed(t)
array.chain.clearFailed()

array.NotValueEqual(0, 123)
array.chain.assertFailed(t)
array.chain.clearFailed()

array.IsValueEqual(1, []interface{}{"456", 789})
array.chain.assertNotFailed(t)
array.chain.clearFailed()

array.NotValueEqual(1, []interface{}{"456", 789})
array.chain.assertFailed(t)
array.chain.clearFailed()

array.IsValueEqual(2, map[string]interface{}{"a": "b"})
array.chain.assertNotFailed(t)
array.chain.clearFailed()

array.NotValueEqual(2, map[string]interface{}{"a": "b"})
array.chain.assertFailed(t)
array.chain.clearFailed()

array.IsValueEqual(2, func() {})
array.chain.assertFailed(t)
array.chain.clearFailed()

array.NotValueEqual(2, func() {})
array.chain.assertFailed(t)
array.chain.clearFailed()

array.IsValueEqual(3, 777)
array.chain.assertFailed(t)
array.chain.clearFailed()

array.NotValueEqual(3, 777)
array.chain.assertFailed(t)
array.chain.clearFailed()

array.IsValueEqual(-1, 999)
array.chain.assertFailed(t)
array.chain.clearFailed()

array.NotValueEqual(-1, 999)
array.chain.assertFailed(t)
array.chain.clearFailed()
}

func TestArray_ValueEqualStruct(t *testing.T) {
reporter := newMockReporter(t)

array := NewArray(reporter, []interface{}{
map[string]interface{}{
"a": map[string]interface{}{
"b": 333,
"c": 444,
},
},
})

type (
A struct {
B int `json:"b"`
C int `json:"c"`
}

Baz struct {
A A `json:"a"`
}
)

baz := Baz{
A: A{
B: 333,
C: 444,
},
}

array.IsValueEqual(0, baz)
array.chain.assertNotFailed(t)
array.chain.clearFailed()

array.NotValueEqual(0, baz)
array.chain.assertFailed(t)
array.chain.clearFailed()

array.IsValueEqual(0, Baz{})
array.chain.assertFailed(t)
array.chain.clearFailed()

array.NotValueEqual(0, Baz{})
array.chain.assertNotFailed(t)
array.chain.clearFailed()
}

func TestArray_ConvertValueEqual(t *testing.T) {
type (
myArray []interface{}
myMap map[string]interface{}
myInt int
)

reporter := newMockReporter(t)

array := NewArray(reporter, []interface{}{
123,
[]interface{}{"456", 789},
map[string]interface{}{
"a": "b",
},
})

array.IsValueEqual(1, myArray{"456", myInt(789)})
array.chain.assertNotFailed(t)
array.chain.clearFailed()

array.NotValueEqual(1, myArray{"456", myInt(789)})
array.chain.assertFailed(t)
array.chain.clearFailed()

array.IsValueEqual(2, myMap{"a": "b"})
array.chain.assertNotFailed(t)
array.chain.clearFailed()

array.NotValueEqual(2, myMap{"a": "b"})
array.chain.assertFailed(t)
array.chain.clearFailed()
}

func TestArray_ComparatorErrors(t *testing.T) {
t.Run("nil_slice", func(t *testing.T) {
chain := newMockChain(t).enter("test")
Expand Down

0 comments on commit b3490ba

Please sign in to comment.