Project

rspec-wait

0.21
No commit activity in last 3 years
No release in over 3 years
There's a lot of open issues
Wait for conditions in RSpec
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.12
~> 11.2

Runtime

< 4, >= 3
 Project Readme

RSpec::Wait

Wait for conditions in RSpec

Gem Version Build Status Code Climate Coverage Status Dependency Status

Why does RSpec::Wait exist?

Timing is hard.

Timing problems and race conditions can plague your test suite. As your test suite slowly becomes less reliable, development speed and quality suffer.

RSpec::Wait strives to make it easier to test asynchronous or slow interactions.

How does RSpec::Wait work?

RSpec::Wait allows you to wait for an assertion to pass, using the RSpec syntactic sugar that you already know and love.

RSpec::Wait will keep trying until your assertion passes or times out.

Example

RSpec::Wait's wait_for assertions are nearly drop-in replacements for RSpec's expect assertions. The major difference is that the wait_for method only works with non-block matchers. However, wait_for will still accept a block because it may need to evaluate the content of that block multiple times while waiting.

describe Ticker do
  subject(:ticker) { Ticker.new("foo") }

  describe "#start" do
    before do
      ticker.start
    end

    it "starts a blank tape" do
      expect(ticker.tape).to eq("")
    end

    it "writes the message one letter at a time" do
      wait_for(ticker.tape).to eq("··-·")
      wait_for(ticker.tape).to eq("··-· ---")
      wait_for(ticker.tape).to eq("··-· --- ---")
    end
  end
end

This can be especially useful for testing user interfaces with tricky timing elements like JavaScript interactions or remote requests.

feature "User Login" do
  let!(:user) { create(:user, email: "john@example.com", password: "secret") }

  scenario "A user can log in successfully" do
    visit new_session_path

    fill_in "Email", with: "john@example.com"
    fill_in "Password", with: "secret"
    click_button "Log In"

    wait_for { current_path }.to eq(account_path)
    expect(page).to have_content("Welcome back!")
  end
end

Matchers

RSpec::Wait ties into RSpec's internals so it can take full advantage of any non-block matcher that you would use with RSpec's own expect method.

Timeout

By default, RSpec::Wait will wait up to 10 seconds for an assertion to pass. That timeout value is configurable in three ways:

RSpec Configuration

RSpec.configure do |config|
  config.wait_timeout = 3 # seconds
end

RSpec Metadata

The timeout can also be specified via options added to a spec's or context's :wait metadata:

scenario "A user can log in successfully", wait: { timeout: 3 } do
  visit new_session_path

  fill_in "Email", with: "john@example.com"
  fill_in "Password", with: "secret"
  click_button "Log In"

  wait_for { current_path }.to eq(account_path)
  expect(page).to have_content("Welcome back!")
end

The wait Method

On a per-assertion basis, the timeout value can be passed to the wait method.

scenario "A user can log in successfully" do
  visit new_session_path

  fill_in "Email", with: "john@example.com"
  fill_in "Password", with: "secret"
  click_button "Log In"

  wait(3.seconds).for { current_path }.to eq(account_path)
  expect(page).to have_content("Welcome back!")
end

Use with Cucumber

To enable RSpec::Wait in your Cucumber step definitions, add the following to features/support/env.rb:

require "rspec/wait"

World(RSpec::Wait)

Who wrote RSpec::Wait?

My name is Steve Richert and I wrote RSpec::Wait in April, 2014 with the support of my employer, Collective Idea. RSpec::Wait owes its current and future success entirely to inspiration and contribution from the Ruby community, especially the authors and maintainers of RSpec.

Thank you!

How can I help?

RSpec::Wait is open source and contributions from the community are encouraged! No contribution is too small.

See RSpec::Wait's contribution guidelines for more information.