I'm having difficulty using Capybara's have_selector
when trying to match for an element where the text matches exactly. I know that this can be done using a regular expression, but my reading of Capybara's blog post led me to believe that I could use an :exact
arg or set Capybara.exact = true
. I am currently using Capybara 2.2.1. Here is what I have:
Assuming that I have a page (called "test page"). On this page is this:
<div id="my_div">abcdef</div>
I have a Cucumber feature test that looks like this:
Feature: Test for exact text matches in have_selector
Scenario:
Given I am on the test page
Then I should get a partial text match "bcde" in my div
And I should get a partial text match "abcdef" in my div
And I should get an exact text match using regexp "abcdef" in my div
And I should not get an exact text match using regexp "bcde" in my div
And I should get an exact text match using arg "abcdef" in my div
And I should not get an exact text match using arg "bcde" in my div
My step definitions look like this:
Then /^I should get a partial text match "([^\"]*)" in my div$/ do |text|
page.should have_selector('div#my_div', :text => text)
end
Then /^I should get an exact text match using regexp "([^\"]*)" in my div$/ do |text|
page.should have_selector('div#my_div', :text => /^#{text}$/)
end
Then /^I should not get an exact text match using regexp "([^\"]*)" in my div$/ do |text|
page.should_not have_selector('div#my_div', :text => /^#{text}$/)
end
Then /^I should get an exact text match using arg "([^\"]*)" in my div$/ do |text|
page.should have_selector('div#my_div', :text => text, :exact => true)
end
Then /^I should not get an exact text match using arg "([^\"]*)" in my div$/ do |text|
page.should_not have_selector('div#my_div', :text => text, :exact => true)
end
Contrary to my expectations, I got the following error:
And I should not get an exact text match using arg "bcde" in my div
expected not to find css "div#my_div" with text "bcde", found 1 match: "abcdef" (Capybara::ExpectationNotMet)
This leads me to believe that :exact => true
is not doing anything in my have_selector
call. I have similarly tried to set Capybara.exact = true
in my test setup configurations, but this also does not seem to affect my tests that I way I would have expected.
Am I missing something? Or am I misunderstanding how this option is supposed to be used? I know that I can always use the regular expression syntax for matching an exact text string, but I would have thought that the :exact
option is specifically for this kind of situation.
There is an open feature request, Capybara Github Issue 1256, to have have_selector
(and others) support exact text matching.
However, for now (in Capybara 2.x), the :exact
option does not apply to the :text
option. If I recall correctly, it is the following piece of code (from query.rb) that does the text option filtering. As you can see, there is no logic or consideration of the :exact
option.
def matches_filters?(node)
if options[:text]
regexp = options[:text].is_a?(Regexp) ? options[:text] : Regexp.escape(options[:text].to_s)
return false if not node.text(visible).match(regexp)
end
As per the Capybara docs, the :exact
option is actually to:
Control whether
is
expressions in the given XPath match exactly or partially
This is basically only used in the Capybara::Node::Actions, where the text (or id, name, etc.) is not specified as an option - ex:
# Will match links that exactly match 'Password'
click_link('Password', :exact => true)
# Will match links that contain the word 'Password' - ex 'Password Confirmation'
click_link('Password', :exact => false)
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