Skip to content

Commit 1f2e714

Browse files
authored
allow users to wrap the Gomega interface (#521)
gomega internally casts to *internal.Gomega which makes wrapping it impossible. To allow this, add an interface that if implemented will be used to get the actual *internal.Gomega. This allows users to replace gomega.Default with their own wrapper as long as it implements provides an 'Inner() Gomega' method.
1 parent 56d2a29 commit 1f2e714

File tree

1 file changed

+26
-12
lines changed

1 file changed

+26
-12
lines changed

gomega_dsl.go

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ var Default = Gomega(internal.NewGomega(internal.FetchDefaultDurationBundle()))
5252
// rich ecosystem of matchers without causing a test to fail. For example, to aggregate a series of potential failures
5353
// or for use in a non-test setting.
5454
func NewGomega(fail types.GomegaFailHandler) Gomega {
55-
return internal.NewGomega(Default.(*internal.Gomega).DurationBundle).ConfigureWithFailHandler(fail)
55+
return internal.NewGomega(internalGomega(Default).DurationBundle).ConfigureWithFailHandler(fail)
5656
}
5757

5858
// WithT wraps a *testing.T and provides `Expect`, `Eventually`, and `Consistently` methods. This allows you to leverage
@@ -69,6 +69,20 @@ type WithT = internal.Gomega
6969
// GomegaWithT is deprecated in favor of gomega.WithT, which does not stutter.
7070
type GomegaWithT = WithT
7171

72+
// inner is an interface that allows users to provide a wrapper around Default. The wrapper
73+
// must implement the inner interface and return either the original Default or the result of
74+
// a call to NewGomega().
75+
type inner interface {
76+
Inner() Gomega
77+
}
78+
79+
func internalGomega(g Gomega) *internal.Gomega {
80+
if v, ok := g.(inner); ok {
81+
return v.Inner().(*internal.Gomega)
82+
}
83+
return g.(*internal.Gomega)
84+
}
85+
7286
// NewWithT takes a *testing.T and returngs a `gomega.WithT` allowing you to use `Expect`, `Eventually`, and `Consistently` along with
7387
// Gomega's rich ecosystem of matchers in standard `testing` test suits.
7488
//
@@ -79,7 +93,7 @@ type GomegaWithT = WithT
7993
// g.Expect(f.HasCow()).To(BeTrue(), "Farm should have cow")
8094
// }
8195
func NewWithT(t types.GomegaTestingT) *WithT {
82-
return internal.NewGomega(Default.(*internal.Gomega).DurationBundle).ConfigureWithT(t)
96+
return internal.NewGomega(internalGomega(Default).DurationBundle).ConfigureWithT(t)
8397
}
8498

8599
// NewGomegaWithT is deprecated in favor of gomega.NewWithT, which does not stutter.
@@ -88,20 +102,20 @@ var NewGomegaWithT = NewWithT
88102
// RegisterFailHandler connects Ginkgo to Gomega. When a matcher fails
89103
// the fail handler passed into RegisterFailHandler is called.
90104
func RegisterFailHandler(fail types.GomegaFailHandler) {
91-
Default.(*internal.Gomega).ConfigureWithFailHandler(fail)
105+
internalGomega(Default).ConfigureWithFailHandler(fail)
92106
}
93107

94108
// RegisterFailHandlerWithT is deprecated and will be removed in a future release.
95109
// users should use RegisterFailHandler, or RegisterTestingT
96110
func RegisterFailHandlerWithT(_ types.GomegaTestingT, fail types.GomegaFailHandler) {
97111
fmt.Println("RegisterFailHandlerWithT is deprecated. Please use RegisterFailHandler or RegisterTestingT instead.")
98-
Default.(*internal.Gomega).ConfigureWithFailHandler(fail)
112+
internalGomega(Default).ConfigureWithFailHandler(fail)
99113
}
100114

101115
// RegisterTestingT connects Gomega to Golang's XUnit style
102116
// Testing.T tests. It is now deprecated and you should use NewWithT() instead to get a fresh instance of Gomega for each test.
103117
func RegisterTestingT(t types.GomegaTestingT) {
104-
Default.(*internal.Gomega).ConfigureWithT(t)
118+
internalGomega(Default).ConfigureWithT(t)
105119
}
106120

107121
// InterceptGomegaFailures runs a given callback and returns an array of
@@ -112,13 +126,13 @@ func RegisterTestingT(t types.GomegaTestingT) {
112126
// This is most useful when testing custom matchers, but can also be used to check
113127
// on a value using a Gomega assertion without causing a test failure.
114128
func InterceptGomegaFailures(f func()) []string {
115-
originalHandler := Default.(*internal.Gomega).Fail
129+
originalHandler := internalGomega(Default).Fail
116130
failures := []string{}
117-
Default.(*internal.Gomega).Fail = func(message string, callerSkip ...int) {
131+
internalGomega(Default).Fail = func(message string, callerSkip ...int) {
118132
failures = append(failures, message)
119133
}
120134
defer func() {
121-
Default.(*internal.Gomega).Fail = originalHandler
135+
internalGomega(Default).Fail = originalHandler
122136
}()
123137
f()
124138
return failures
@@ -131,14 +145,14 @@ func InterceptGomegaFailures(f func()) []string {
131145
// does not register a failure with the FailHandler registered via RegisterFailHandler - it is up
132146
// to the user to decide what to do with the returned error
133147
func InterceptGomegaFailure(f func()) (err error) {
134-
originalHandler := Default.(*internal.Gomega).Fail
135-
Default.(*internal.Gomega).Fail = func(message string, callerSkip ...int) {
148+
originalHandler := internalGomega(Default).Fail
149+
internalGomega(Default).Fail = func(message string, callerSkip ...int) {
136150
err = errors.New(message)
137151
panic("stop execution")
138152
}
139153

140154
defer func() {
141-
Default.(*internal.Gomega).Fail = originalHandler
155+
internalGomega(Default).Fail = originalHandler
142156
if e := recover(); e != nil {
143157
if err == nil {
144158
panic(e)
@@ -151,7 +165,7 @@ func InterceptGomegaFailure(f func()) (err error) {
151165
}
152166

153167
func ensureDefaultGomegaIsConfigured() {
154-
if !Default.(*internal.Gomega).IsConfigured() {
168+
if !internalGomega(Default).IsConfigured() {
155169
panic(nilGomegaPanic)
156170
}
157171
}

0 commit comments

Comments
 (0)