I'm using RSpec2 and Capybara for acceptance testing.
I would like to assert that link is disabled or not in Capybara. How can I do this?
I'm using RSpec2 and Capybara for acceptance testing.
I would like to assert that link is disabled or not in Capybara. How can I do this?
How are you disabling the link? Is it a class you're adding? An attribute?
# Check for a link that has a "disabled" class:
page.should have_css("a.my_link.disabled")
page.should have_xpath("//a[@class='disabled']")
# Check for a link that has a "disabled" attribute:
page.should have_css("a.my_link[disabled]")
page.should have_xpath("//a[@class='disabled' and @disabled='disabled']")
# Check that the element is visible
find("a.my_link").should be_visible
find(:xpath, "//a[@class='disabled']").should be_visible
The actual xpath selectors may be incorrect. I don't use xpath often!
Another simple solution is to access the HTML attribute you are looking for with []
:
find('#my_element')['class']
# => "highlighted clearfix some_other_css_class"
find('a#my_element')['href']
# => "http://example.com
# or in general, find any attribute, even if it does not exist
find('a#my_element')['no_such_attribute']
# => ""
Note that Capybara
will automatically try to wait for asynchronous requests to finish, but it may not work in some cases:
Here is one workaround if you are having trouble with assertions on elements that are updated asynchronously:
It was a bit messy to find out the correct xpath, here is the correct one,
using capybara 0.4.1.1
# <a href="/clowns?ordered_by=clumsyness" class="weep">View Clowns</a>
page.should have_xpath("//a[@class='weep'][@href='/clowns?ordered_by=clumsyness']", :text => "View Clowns")
If you only have a link without a class, use
page.should have_link('View Clowns', :href => '/clowns?ordered_by=clumsyness')
Something like this will sadly not work:
page.should have_link('This will not work!', :href => '/clowns?ordered_by=clumsyness', :class => "weep")
The class option will be ignored.
I recommend using have_link
and find_link(name)[:disabled]
in two separate assertions. While performing the second assertion alone is simpler, this makes error messages about missing links look nicer, making your test results easier to read.
expect(page).to have_link "Example"
expect(find_link("Example")[:disabled]).to be false
Note that "Example"
can be changed to the name or id of the link.
page.should have_link('It will work this way!', {:href => '/clowns?ordered_by=clumsyness', :class => "smile"})
have_link expects a hash of options which is empty if you do not provide any. You can specify any attributes the link should have - just make sure you pass all the options in ONE hash.
Hope this helps
PS: For attributes like data-method you have to pass the attribute name as a string since the hyphen breaks the symbol.
Whenever possible, you should try to use the Capybara provided wrappers which will work more consistently across drivers.
For the particular case of disabled
, a wrapper was introduced in 2.1: https://github.com/jnicklas/capybara/blob/fc56557a5463b9d944207f2efa401faa5b49d9ef/History.md#version-210
If you use it, you will get sensible results on both RackTest and Poltergeist:
HTML:
<input type="text" id="disabled-false" ></div>
<input type="text" id="disabled-true" disabled></div>
<input type="text" id="disabled-js-true" ></div>
<input type="text" id="disabled-js-false" disabled></div>
<script>
document.getElementById('disabled-js-true').disabled = true
document.getElementById('disabled-js-false').disabled = false
</script>
Tests:
!all(:field, 'disabled-false', disabled: false).empty? or raise
all(:field, 'disabled-false', disabled: true ).empty? or raise
all(:field, 'disabled-true', disabled: false).empty? or raise
!all(:field, 'disabled-true', disabled: true ).empty? or raise
all(:field, 'disabled-js-true', disabled: true ).empty? or raise
all(:field, 'disabled-js-false', disabled: false).empty? or raise
Capybara.current_driver = :poltergeist
!all(:field, 'disabled-false', disabled: false).empty? or raise
all(:field, 'disabled-false', disabled: true ).empty? or raise
all(:field, 'disabled-true', disabled: false).empty? or raise
!all(:field, 'disabled-true', disabled: true ).empty? or raise
!all(:field, 'disabled-js-true', disabled: true ).empty? or raise
!all(:field, 'disabled-js-false', disabled: false).empty? or raise
Note how by using this instead of CSS selectors, the Javascript tests will work without any changes if you start using a Js capable driver.
Runnable test file here.
bowsersenior, thanks for a hint
Another simple solution is to access the HTML attribute you are looking for with []
Here is an example:
let(:action_items) { page.find('div.action_items') }
it "action items displayed as buttons" do
action_items.all(:css, 'a').each do |ai|
expect(ai[:class]).to match(/btn/)
end
end
Using Rspec3's syntax i did it this way:
expect(page).not_to have_selector(:link_or_button, 'Click here')
Simply you can use page.has_css?
method
page.has_css?('.class_name')
this will return true
if element exists.
Do some action based on validation.
page.has_css?('.class_name') do
#some code
end
According to the docs you can use the [attribute] accessor syntax:
find('#selector')['class'] => "form-control text optional disabled"
For disabled, you could also do this:
expect(find('#selector').disabled?).to be(true)