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

Waiting matcher #580

Closed
abotalov opened this issue Jun 15, 2014 · 8 comments
Closed

Waiting matcher #580

abotalov opened this issue Jun 15, 2014 · 8 comments

Comments

@abotalov
Copy link
Contributor

I'd like to propose to add a matcher that will retry given block until it will match all other matchers or time expired.

The matcher is applied to other matchers (like Compound).

Usage examples:

expect { find('#id')[:class] }.to eq('some_class').during(3, every: 0.2)
expect { response.headers }.to include({'Content-type' => 'text/html'}).and include({'Content-Encoding' => 'gzip'}).during(2)

Currently users should use some gem like retriable or some other form of wait_until like:

wait_until(3) { find('#id')[:class] == 'some_class' }
Retriable.retriable :on => Timeout::Error, :tries => 3, :interval => 1 do
  find('#id')[:class] == 'some_class'
end

So error messages don't tell what was the actual value of e.g. find('#id')[:class] in those cases. I think handling this issue at RSpec side instead of adding additional waiting matchers to e.g. Capybara would be a more proper solution since its not webapp-only problem.

Please tell if you think the idea is good or not.

@JonRowe
Copy link
Member

JonRowe commented Jun 16, 2014

In general I don't think RSpec should handle this, Ruby is not, in general, asynchronous so it's up to the code under test to block and return the correct value when dealing with something that is. We also can't guarantee we wouldn't prevent the block from working as we don't know what we're waiting for.

Capybara handles this for you when dealing with browsers because it knows you are waiting for an external process to do something so it is able to safely block and wait for that to finish. It doesn't do it with rack-test for example. If all you want is more detail in the error output for Capybara I'd suggest you suggest it to them!

@JonRowe
Copy link
Member

JonRowe commented Jun 16, 2014

You could also implement this as a gem, or within your own codebase RSpec does allow you to define custom matchers.

@myronmarston
Copy link
Member

I agree with @JonRowe: I don't think this belongs in RSpec. You mention it's not a webapp-only problem, but in the ~5 years I've been using RSpec, I've never wanted or needed something like this. I think this could work well as an extension gem, though. If you decide to make one and need some additional extension points to integrate, let us know.

@abotalov
Copy link
Contributor Author

Currently matchers like eq or include have supports_block_expectations? set to false. So it seems to me adding such a matcher would require at least setting it true and invoking .call if it's a block.

@myronmarston
Copy link
Member

You can certainly override supports_block_expectations? in those matchers, but you should be aware of the discussions that went into that design:

@abotalov
Copy link
Contributor Author

@myronmarston Thanks. I wrote some code (https://github.com/abotalov/waiting_rspec_matchers/blob/master/lib/waiting_rspec_matchers.rb) that just adds new "become_*" rspec matchers. I would be happy if you'll review it.

@myronmarston
Copy link
Member

Sounds like you've found something that works for you. That's great.

@bootstraponline
Copy link

There's also wait_for via the rspec-wait gem which is cool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants