blob: 4159335d0d5aecb8c2efc27b6bee1b2ef5f2a692 [file] [log] [blame]
Matthias Andreas Benkard832a54e2019-01-29 09:27:38 +01001package matchers
2
3import (
4 "fmt"
5 "reflect"
6
7 "github.com/onsi/gomega/format"
8)
9
10type ContainElementMatcher struct {
11 Element interface{}
12}
13
14func (matcher *ContainElementMatcher) Match(actual interface{}) (success bool, err error) {
15 if !isArrayOrSlice(actual) && !isMap(actual) {
16 return false, fmt.Errorf("ContainElement matcher expects an array/slice/map. Got:\n%s", format.Object(actual, 1))
17 }
18
19 elemMatcher, elementIsMatcher := matcher.Element.(omegaMatcher)
20 if !elementIsMatcher {
21 elemMatcher = &EqualMatcher{Expected: matcher.Element}
22 }
23
24 value := reflect.ValueOf(actual)
25 var keys []reflect.Value
26 if isMap(actual) {
27 keys = value.MapKeys()
28 }
29 var lastError error
30 for i := 0; i < value.Len(); i++ {
31 var success bool
32 var err error
33 if isMap(actual) {
34 success, err = elemMatcher.Match(value.MapIndex(keys[i]).Interface())
35 } else {
36 success, err = elemMatcher.Match(value.Index(i).Interface())
37 }
38 if err != nil {
39 lastError = err
40 continue
41 }
42 if success {
43 return true, nil
44 }
45 }
46
47 return false, lastError
48}
49
50func (matcher *ContainElementMatcher) FailureMessage(actual interface{}) (message string) {
51 return format.Message(actual, "to contain element matching", matcher.Element)
52}
53
54func (matcher *ContainElementMatcher) NegatedFailureMessage(actual interface{}) (message string) {
55 return format.Message(actual, "not to contain element matching", matcher.Element)
56}