I'm just getting started with feature specs using RSpec (and Capybara). I'm testing my ActiveAdmin dashboard and I want to check that all panels have an orders table as shown in this snippet:
feature 'admin dashboard', type: :feature do
def panels
page.all('.column .panel')
end
describe 'all panels' do
it 'have an orders table' do
expect(panels).to all(have_css('table.orders tbody'))
end
end
end
I've used the all
matcher a lot in my unit tests but it doesn't appear to work when wrapping Capybara's have_css
matcher because I'm getting the following error:
Failure/Error: expect(panels).to all(have_css('table.orders tbody'))
TypeError:
no implicit conversion of Capybara::RackTest::CSSHandlers into String
Am I correct in my assumption that RSpec's built-in all
matcher should work with other matchers as well?
Note: I'm using describe
and it
instead of feature
and scenario
in this instance because I'm testing output rather than user interaction scenarios (see my other question).
Unfortunately there is a conflict between RSpec's all
and Capybara's all
see Capybara Issue 1396. The all
that you are calling is actually Capybara's all
.
Solution 1 - Call BuiltIn::All Directly
The quickest solution would be to call RSpec's all
method directly (or at least that code that it executes.
The expectation will work if you use RSpec::Matchers::BuiltIn::All.new
instead of all
:
expect(panels).to RSpec::Matchers::BuiltIn::All.new(have_css('table.orders tbody'))
Solution 2 - Redefine all
Calling the BuiltIn:All directly does not read nicely so might get annoying if used often. An alternative would be to re-define the all
method to be RSpec's all
method. To do this, add the module and configuration:
module FixAll
def all(expected)
RSpec::Matchers::BuiltIn::All.new(expected)
end
end
RSpec.configure do |c|
c.include FixAll
end
With the change, the all
in the following line will behave like RSpec's all
method.
expect(panels).to all(have_css('table.orders tbody'))
Note that if you want to use Capybara's all
method, you would now always need to call it using the session (ie page
):
# This will work because "page.all" is used
expect(page.all('table').length).to eq(2)
# This will throw an exception since "all" is used
expect(all('table').length).to eq(2)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With