diff --git a/matchers/consist_of.go b/matchers/consist_of.go index e8ef0dee1..f69037a4f 100644 --- a/matchers/consist_of.go +++ b/matchers/consist_of.go @@ -48,11 +48,13 @@ func neighbours(value, matcher interface{}) (bool, error) { func equalMatchersToElements(matchers []interface{}) (elements []interface{}) { for _, matcher := range matchers { - equalMatcher, ok := matcher.(*EqualMatcher) - if ok { - matcher = equalMatcher.Expected + if equalMatcher, ok := matcher.(*EqualMatcher); ok { + elements = append(elements, equalMatcher.Expected) + } else if _, ok := matcher.(*BeNilMatcher); ok { + elements = append(elements, nil) + } else { + elements = append(elements, matcher) } - elements = append(elements, matcher) } return } @@ -72,11 +74,13 @@ func flatten(elems []interface{}) []interface{} { func matchers(expectedElems []interface{}) (matchers []interface{}) { for _, e := range flatten(expectedElems) { - matcher, isMatcher := e.(omegaMatcher) - if !isMatcher { - matcher = &EqualMatcher{Expected: e} + if e == nil { + matchers = append(matchers, &BeNilMatcher{}) + } else if matcher, isMatcher := e.(omegaMatcher); isMatcher { + matchers = append(matchers, matcher) + } else { + matchers = append(matchers, &EqualMatcher{Expected: e}) } - matchers = append(matchers, matcher) } return } @@ -89,9 +93,14 @@ func presentable(elems []interface{}) interface{} { } sv := reflect.ValueOf(elems) - tt := sv.Index(0).Elem().Type() + firstEl := sv.Index(0) + if firstEl.IsNil() { + return elems + } + tt := firstEl.Elem().Type() for i := 1; i < sv.Len(); i++ { - if sv.Index(i).Elem().Type() != tt { + el := sv.Index(i) + if el.IsNil() || (sv.Index(i).Elem().Type() != tt) { return elems } } diff --git a/matchers/consist_of_test.go b/matchers/consist_of_test.go index 76a739839..c7149b714 100644 --- a/matchers/consist_of_test.go +++ b/matchers/consist_of_test.go @@ -74,6 +74,13 @@ var _ = Describe("ConsistOf", func() { }) }) + When("provided an expectation that has a nil value", func() { + It("should match without failure", func() { + Expect([]any{1, "two", nil}).Should(ConsistOf([]any{nil, 1, "two"})) + Expect([]any{1, "two", "nil", nil}).ShouldNot(ConsistOf([]any{nil, nil, 1, "two"})) + }) + }) + Describe("FailureMessage", func() { When("actual contains an extra element", func() { It("prints the extra element", func() { @@ -97,6 +104,17 @@ var _ = Describe("ConsistOf", func() { }) }) + When("actual misses a nil element", func() { + It("prints the missing element", func() { + failures := InterceptGomegaFailures(func() { + Expect([]int{2}).Should(ConsistOf(nil, 2)) + }) + + expected := "Expected\n.*\\[2\\]\nto consist of\n.*\\[nil, 2\\]\nthe missing elements were\n.*\\[nil\\]" + Expect(failures).To(ConsistOf(MatchRegexp(expected))) + }) + }) + When("actual contains an extra element and misses an element", func() { It("prints both the extra and missing element", func() { failures := InterceptGomegaFailures(func() { diff --git a/matchers/have_exact_elements_test.go b/matchers/have_exact_elements_test.go index 7405e5f3e..734a425f2 100644 --- a/matchers/have_exact_elements_test.go +++ b/matchers/have_exact_elements_test.go @@ -13,6 +13,10 @@ var _ = Describe("HaveExactElements", func() { Expect([]string{"foo", "bar"}).ShouldNot(HaveExactElements("foo", "bar", "baz")) Expect([]string{"foo", "bar"}).ShouldNot(HaveExactElements("bar", "foo")) }) + + It("should work with arbitrary types, including nil", func() { + Expect([]any{"foo", nil, "bar", 17, true, []string{"hi", "there"}}).Should(HaveExactElements("foo", nil, "bar", 17, true, []string{"hi", "there"})) + }) }) Context("with an array", func() { It("should do the right thing", func() {