-
-
Notifications
You must be signed in to change notification settings - Fork 282
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add ContainElements matcher Resolves #361 * Convert variable to constant function * Add negative tests
- Loading branch information
Showing
5 changed files
with
191 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package matchers | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/onsi/gomega/format" | ||
"github.com/onsi/gomega/matchers/support/goraph/bipartitegraph" | ||
) | ||
|
||
type ContainElementsMatcher struct { | ||
Elements []interface{} | ||
missingElements []interface{} | ||
} | ||
|
||
func (matcher *ContainElementsMatcher) Match(actual interface{}) (success bool, err error) { | ||
if !isArrayOrSlice(actual) && !isMap(actual) { | ||
return false, fmt.Errorf("ContainElements matcher expects an array/slice/map. Got:\n%s", format.Object(actual, 1)) | ||
} | ||
|
||
matchers := matchers(matcher.Elements) | ||
bipartiteGraph, err := bipartitegraph.NewBipartiteGraph(valuesOf(actual), matchers, neighbours) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
edges := bipartiteGraph.LargestMatching() | ||
if len(edges) == len(matchers) { | ||
return true, nil | ||
} | ||
|
||
_, missingMatchers := bipartiteGraph.FreeLeftRight(edges) | ||
matcher.missingElements = equalMatchersToElements(missingMatchers) | ||
|
||
return false, nil | ||
} | ||
|
||
func (matcher *ContainElementsMatcher) FailureMessage(actual interface{}) (message string) { | ||
message = format.Message(actual, "to contain elements", matcher.Elements) | ||
return appendMissingElements(message, matcher.missingElements) | ||
} | ||
|
||
func (matcher *ContainElementsMatcher) NegatedFailureMessage(actual interface{}) (message string) { | ||
return format.Message(actual, "not to contain elements", matcher.Elements) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package matchers_test | ||
|
||
import ( | ||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
var _ = Describe("ContainElements", func() { | ||
Context("with a slice", func() { | ||
It("should do the right thing", func() { | ||
Expect([]string{"foo", "bar", "baz"}).Should(ContainElements("foo", "bar", "baz")) | ||
Expect([]string{"foo", "bar", "baz"}).Should(ContainElements("bar")) | ||
Expect([]string{"foo", "bar", "baz"}).Should(ContainElements()) | ||
Expect([]string{"foo", "bar", "baz"}).ShouldNot(ContainElements("baz", "bar", "foo", "foo")) | ||
}) | ||
}) | ||
|
||
Context("with an array", func() { | ||
It("should do the right thing", func() { | ||
Expect([3]string{"foo", "bar", "baz"}).Should(ContainElements("foo", "bar", "baz")) | ||
Expect([3]string{"foo", "bar", "baz"}).Should(ContainElements("bar")) | ||
Expect([3]string{"foo", "bar", "baz"}).Should(ContainElements()) | ||
Expect([3]string{"foo", "bar", "baz"}).ShouldNot(ContainElements("baz", "bar", "foo", "foo")) | ||
}) | ||
}) | ||
|
||
Context("with a map", func() { | ||
It("should apply to the values", func() { | ||
Expect(map[int]string{1: "foo", 2: "bar", 3: "baz"}).Should(ContainElements("foo", "bar", "baz")) | ||
Expect(map[int]string{1: "foo", 2: "bar", 3: "baz"}).Should(ContainElements("bar")) | ||
Expect(map[int]string{1: "foo", 2: "bar", 3: "baz"}).Should(ContainElements()) | ||
Expect(map[int]string{1: "foo", 2: "bar", 3: "baz"}).ShouldNot(ContainElements("baz", "bar", "foo", "foo")) | ||
}) | ||
|
||
}) | ||
|
||
Context("with anything else", func() { | ||
It("should error", func() { | ||
failures := InterceptGomegaFailures(func() { | ||
Expect("foo").Should(ContainElements("f", "o", "o")) | ||
}) | ||
|
||
Expect(failures).Should(HaveLen(1)) | ||
}) | ||
}) | ||
|
||
Context("when passed matchers", func() { | ||
It("should pass if the matchers pass", func() { | ||
Expect([]string{"foo", "bar", "baz"}).Should(ContainElements("foo", MatchRegexp("^ba"), "baz")) | ||
Expect([]string{"foo", "bar", "baz"}).Should(ContainElements("foo", MatchRegexp("^ba"))) | ||
Expect([]string{"foo", "bar", "baz"}).ShouldNot(ContainElements("foo", MatchRegexp("^ba"), MatchRegexp("foo"))) | ||
Expect([]string{"foo", "bar", "baz"}).Should(ContainElements("foo", MatchRegexp("^ba"), MatchRegexp("^ba"))) | ||
Expect([]string{"foo", "bar", "baz"}).ShouldNot(ContainElements("foo", MatchRegexp("^ba"), MatchRegexp("turducken"))) | ||
}) | ||
|
||
It("should not depend on the order of the matchers", func() { | ||
Expect([][]int{{1, 2}, {2}}).Should(ContainElements(ContainElement(1), ContainElement(2))) | ||
Expect([][]int{{1, 2}, {2}}).Should(ContainElements(ContainElement(2), ContainElement(1))) | ||
}) | ||
|
||
Context("when a matcher errors", func() { | ||
It("should soldier on", func() { | ||
Expect([]string{"foo", "bar", "baz"}).ShouldNot(ContainElements(BeFalse(), "foo", "bar")) | ||
Expect([]interface{}{"foo", "bar", false}).Should(ContainElements(BeFalse(), ContainSubstring("foo"), "bar")) | ||
}) | ||
}) | ||
}) | ||
|
||
Context("when passed exactly one argument, and that argument is a slice", func() { | ||
It("should match against the elements of that argument", func() { | ||
Expect([]string{"foo", "bar", "baz"}).Should(ContainElements([]string{"foo", "baz"})) | ||
Expect([]string{"foo", "bar", "baz"}).ShouldNot(ContainElements([]string{"foo", "nope"})) | ||
}) | ||
}) | ||
|
||
Describe("FailureMessage", func() { | ||
It("prints missing elements", func() { | ||
failures := InterceptGomegaFailures(func() { | ||
Expect([]int{2}).Should(ContainElements(1, 2, 3)) | ||
}) | ||
|
||
expected := "Expected\n.*\\[2\\]\nto contain elements\n.*\\[1, 2, 3\\]\nthe missing elements were\n.*\\[1, 3\\]" | ||
Expect(failures).To(ContainElements(MatchRegexp(expected))) | ||
}) | ||
}) | ||
}) |