Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introduces Eventually.Within.ProbeEvery with tests and documentation #591

Merged
merged 1 commit into from Sep 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/index.md
Expand Up @@ -252,10 +252,11 @@ The first optional argument is the timeout (which defaults to 1s), the second is

> As with synchronous assertions, you can annotate asynchronous assertions by passing either a format string and optional inputs or a function of type `func() string` after the `GomegaMatcher`.

Alternatively, the timeout and polling interval can also be specified by chaining `WithTimeout` and `WithPolling` to `Eventually`:
Alternatively, the timeout and polling interval can also be specified by chaining `Within` and `ProbeEvery` or `WithTimeout` and `WithPolling` to `Eventually`:

```go
Eventually(ACTUAL).WithTimeout(TIMEOUT).WithPolling(POLLING_INTERVAL).Should(MATCHER)
Eventually(ACTUAL).Within(TIMEOUT).ProbeEvery(POLLING_INTERVAL).Should(MATCHER)
```

Eventually works with any Gomega compatible matcher and supports making assertions against three categories of `ACTUAL` value:
Expand Down
10 changes: 10 additions & 0 deletions internal/async_assertion.go
Expand Up @@ -102,6 +102,16 @@ func (assertion *AsyncAssertion) WithPolling(interval time.Duration) types.Async
return assertion
}

func (assertion *AsyncAssertion) Within(timeout time.Duration) types.AsyncAssertion {
assertion.timeoutInterval = timeout
return assertion
}

func (assertion *AsyncAssertion) ProbeEvery(interval time.Duration) types.AsyncAssertion {
assertion.pollingInterval = interval
return assertion
}

func (assertion *AsyncAssertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
assertion.g.THelper()
vetOptionalDescription("Asynchronous assertion", optionalDescription...)
Expand Down
22 changes: 21 additions & 1 deletion internal/async_assertion_test.go
Expand Up @@ -59,6 +59,26 @@ var _ = Describe("Asynchronous Assertions", func() {
Ω(ig.FailureMessage).Should(ContainSubstring("positive: no match"))
Ω(ig.FailureSkip).Should(Equal([]int{3}))
})

It("maps Within() correctly to timeout and polling intervals", func() {
counter := 0
ig.G.Eventually(func() bool {
counter++
return false
}).WithTimeout(0).WithPolling(20 * time.Millisecond).Within(200 * time.Millisecond).Should(BeTrue())
Ω(counter).Should(BeNumerically(">", 2))
Ω(counter).Should(BeNumerically("<", 20))

counter = 0
ig.G.Eventually(func() bool {
counter++
return false
}).WithTimeout(0).WithPolling(0). // first zero intervals, then set them
Within(200 * time.Millisecond).ProbeEvery(20 * time.Millisecond).
Should(BeTrue())
Ω(counter).Should(BeNumerically(">", 2))
Ω(counter).Should(BeNumerically("<", 20))
})
})

Context("the negative case", func() {
Expand Down Expand Up @@ -309,7 +329,7 @@ var _ = Describe("Asynchronous Assertions", func() {
})
})

Context("when passed a function that takes no arguments and returns mutliple values", func() {
Context("when passed a function that takes no arguments and returns multiple values", func() {
Context("with Eventually", func() {
It("polls the function until the first returned value satisfies the matcher _and_ all additional values are zero", func() {
counter, s, f, err := 0, "hi", Foo{Bar: "hi"}, errors.New("hi")
Expand Down
8 changes: 5 additions & 3 deletions types/types.go
Expand Up @@ -6,7 +6,7 @@ import (

type GomegaFailHandler func(message string, callerSkip ...int)

//A simple *testing.T interface wrapper
// A simple *testing.T interface wrapper
type GomegaTestingT interface {
Helper()
Fatalf(format string, args ...interface{})
Expand All @@ -30,9 +30,9 @@ type Gomega interface {
SetDefaultConsistentlyPollingInterval(time.Duration)
}

//All Gomega matchers must implement the GomegaMatcher interface
// All Gomega matchers must implement the GomegaMatcher interface
//
//For details on writing custom matchers, check out: http://onsi.github.io/gomega/#adding-your-own-matchers
// For details on writing custom matchers, check out: http://onsi.github.io/gomega/#adding-your-own-matchers
type GomegaMatcher interface {
Match(actual interface{}) (success bool, err error)
FailureMessage(actual interface{}) (message string)
Expand Down Expand Up @@ -70,6 +70,8 @@ type AsyncAssertion interface {
WithOffset(offset int) AsyncAssertion
WithTimeout(interval time.Duration) AsyncAssertion
WithPolling(interval time.Duration) AsyncAssertion
Within(timeout time.Duration) AsyncAssertion
ProbeEvery(interval time.Duration) AsyncAssertion
}

// Assertions are returned by Ω and Expect and enable assertions against Gomega matchers
Expand Down