1 package matchers_test
2
3 import (
4 . "github.com/onsi/ginkgo/v2"
5 . "github.com/onsi/gomega"
6 . "github.com/onsi/gomega/matchers"
7 )
8
9 var _ = Describe("ContainElement", func() {
10 Describe("matching only", func() {
11 When("passed a supported type", func() {
12 Context("and expecting a non-matcher", func() {
13 It("should do the right thing", func() {
14 Expect([2]int{1, 2}).Should(ContainElement(2))
15 Expect([2]int{1, 2}).ShouldNot(ContainElement(3))
16
17 Expect([]int{1, 2}).Should(ContainElement(2))
18 Expect([]int{1, 2}).ShouldNot(ContainElement(3))
19
20 Expect(map[string]int{"foo": 1, "bar": 2}).Should(ContainElement(2))
21 Expect(map[int]int{3: 1, 4: 2}).ShouldNot(ContainElement(3))
22
23 arr := make([]myCustomType, 2)
24 arr[0] = myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}
25 arr[1] = myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "c"}}
26 Expect(arr).Should(ContainElement(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}))
27 Expect(arr).ShouldNot(ContainElement(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"b", "c"}}))
28 })
29 })
30
31 Context("and expecting a matcher", func() {
32 It("should pass each element through the matcher", func() {
33 Expect([]int{1, 2, 3}).Should(ContainElement(BeNumerically(">=", 3)))
34 Expect([]int{1, 2, 3}).ShouldNot(ContainElement(BeNumerically(">", 3)))
35 Expect(map[string]int{"foo": 1, "bar": 2}).Should(ContainElement(BeNumerically(">=", 2)))
36 Expect(map[string]int{"foo": 1, "bar": 2}).ShouldNot(ContainElement(BeNumerically(">", 2)))
37 })
38
39 It("should power through even if the matcher ever fails", func() {
40 Expect([]interface{}{1, 2, "3", 4}).Should(ContainElement(BeNumerically(">=", 3)))
41 })
42
43 It("should fail if the matcher fails", func() {
44 actual := []interface{}{1, 2, "3", "4"}
45 success, err := (&ContainElementMatcher{Element: BeNumerically(">=", 3)}).Match(actual)
46 Expect(success).Should(BeFalse())
47 Expect(err).Should(HaveOccurred())
48 })
49 })
50 })
51
52 When("passed a correctly typed nil", func() {
53 It("should operate succesfully on the passed in value", func() {
54 var nilSlice []int
55 Expect(nilSlice).ShouldNot(ContainElement(1))
56
57 var nilMap map[int]string
58 Expect(nilMap).ShouldNot(ContainElement("foo"))
59 })
60 })
61
62 When("passed an unsupported type", func() {
63 It("should error", func() {
64 success, err := (&ContainElementMatcher{Element: 0}).Match(0)
65 Expect(success).Should(BeFalse())
66 Expect(err).Should(HaveOccurred())
67
68 success, err = (&ContainElementMatcher{Element: 0}).Match("abc")
69 Expect(success).Should(BeFalse())
70 Expect(err).Should(HaveOccurred())
71
72 success, err = (&ContainElementMatcher{Element: 0}).Match(nil)
73 Expect(success).Should(BeFalse())
74 Expect(err).Should(HaveOccurred())
75 })
76 })
77 })
78
79 Describe("returning findings", func() {
80 It("rejects a nil result reference", func() {
81 Expect(ContainElement("foo", nil).Match([]string{"foo"})).Error().To(
82 MatchError(MatchRegexp(`expects a non-nil pointer.+ Got\n +<nil>: nil`)))
83 })
84
85 Context("with match(es)", func() {
86 When("passed an assignable result reference", func() {
87 It("should assign a single finding to a scalar result reference", func() {
88 actual := []string{"bar", "foo"}
89 var stash string
90 Expect(actual).To(ContainElement("foo", &stash))
91 Expect(stash).To(Equal("foo"))
92
93 actualmap := map[int]string{
94 1: "bar",
95 2: "foo",
96 }
97 Expect(actualmap).To(ContainElement("foo", &stash))
98 Expect(stash).To(Equal("foo"))
99 })
100
101 It("should assign a single finding to a slice return reference", func() {
102 actual := []string{"bar", "foo", "baz"}
103 var stash []string
104 Expect(actual).To(ContainElement("foo", &stash))
105 Expect(stash).To(HaveLen(1))
106 Expect(stash).To(ContainElement("foo"))
107 })
108
109 It("should assign multiple findings to a slice return reference", func() {
110 actual := []string{"bar", "foo", "bar", "foo"}
111 var stash []string
112 Expect(actual).To(ContainElement("foo", &stash))
113 Expect(stash).To(HaveLen(2))
114 Expect(stash).To(HaveEach("foo"))
115 })
116
117 It("should assign map findings to a map return reference", func() {
118 actual := map[string]string{
119 "foo": "foo",
120 "bar": "bar",
121 "baz": "baz",
122 }
123 var stash map[string]string
124 Expect(actual).To(ContainElement(ContainSubstring("ba"), &stash))
125 Expect(stash).To(HaveLen(2))
126 Expect(stash).To(ConsistOf("bar", "baz"))
127 })
128 })
129
130 When("passed a scalar return reference for multiple matches", func() {
131 It("should error", func() {
132 actual := []string{"foo", "foo"}
133 var stash string
134 Expect(ContainElement("foo", &stash).Match(actual)).Error().To(
135 MatchError(MatchRegexp(`cannot return multiple findings\. Need \*\[\]string, got \*string`)))
136 })
137 })
138
139 When("passed an unassignable return reference for matches", func() {
140 It("should error for actual []T1, return reference T2", func() {
141 actual := []string{"bar", "foo"}
142 var stash int
143 Expect(ContainElement("foo", &stash).Match(actual)).Error().To(HaveOccurred())
144 })
145 It("should error for actual []T, return reference [...]T", func() {
146 actual := []string{"bar", "foo"}
147 var arrstash [2]string
148 Expect(ContainElement("foo", &arrstash).Match(actual)).Error().To(HaveOccurred())
149 })
150 It("should error for actual []interface{}, return reference T", func() {
151 actual := []interface{}{"foo", 42}
152 var stash int
153 Expect(ContainElement(Not(BeZero()), &stash).Match(actual)).Error().To(
154 MatchError(MatchRegexp(`cannot return findings\. Need \*interface.+, got \*int`)))
155 })
156 It("should error for actual []interface{}, return reference []T", func() {
157 actual := []interface{}{"foo", 42}
158 var stash []string
159 Expect(ContainElement(Not(BeZero()), &stash).Match(actual)).Error().To(
160 MatchError(MatchRegexp(`cannot return findings\. Need \*\[\]interface.+, got \*\[\]string`)))
161 })
162 It("should error for actual map[T]T, return reference map[T]interface{}", func() {
163 actual := map[string]string{
164 "foo": "foo",
165 "bar": "bar",
166 "baz": "baz",
167 }
168 var stash map[string]interface{}
169 Expect(ContainElement(Not(BeZero()), &stash).Match(actual)).Error().To(
170 MatchError(MatchRegexp(`cannot return findings\. Need \*map\[string\]string, got \*map\[string\]interface`)))
171 })
172 It("should error for actual map[T]T, return reference []T", func() {
173 actual := map[string]string{
174 "foo": "foo",
175 "bar": "bar",
176 "baz": "baz",
177 }
178 var stash []string
179 Expect(ContainElement(Not(BeZero()), &stash).Match(actual)).Error().To(
180 MatchError(MatchRegexp(`cannot return findings\. Need \*map\[string\]string, got \*\[\]string`)))
181 })
182
183 It("should return a descriptive return reference-type error", func() {
184 actual := []string{"bar", "foo"}
185 var stash map[string]struct{}
186 Expect(ContainElement("foo", &stash).Match(actual)).Error().To(
187 MatchError(MatchRegexp(`cannot return findings\. Need \*\[\]string, got \*map`)))
188 })
189 })
190 })
191
192 Context("without any matches", func() {
193 When("the matcher did not error", func() {
194 It("should report non-match", func() {
195 actual := []string{"bar", "foo"}
196 var stash string
197 rem := ContainElement("baz", &stash)
198 m, err := rem.Match(actual)
199 Expect(m).To(BeFalse())
200 Expect(err).NotTo(HaveOccurred())
201 Expect(rem.FailureMessage(actual)).To(MatchRegexp(`Expected\n.+\nto contain element matching\n.+: baz`))
202
203 var stashslice []string
204 rem = ContainElement("baz", &stashslice)
205 m, err = rem.Match(actual)
206 Expect(m).To(BeFalse())
207 Expect(err).NotTo(HaveOccurred())
208 Expect(rem.FailureMessage(actual)).To(MatchRegexp(`Expected\n.+\nto contain element matching\n.+: baz`))
209 })
210 })
211
212 When("the matcher errors", func() {
213 It("should report last matcher error", func() {
214 actual := []interface{}{"bar", 42}
215 var stash []interface{}
216 Expect(ContainElement(HaveField("yeehaw", 42), &stash).Match(actual)).Error().To(MatchError(MatchRegexp(`HaveField encountered:\n.*<int>: 42\nWhich is not a struct`)))
217 })
218 })
219 })
220 })
221
222 })
223
View as plain text