Using Capybara determine whether a form field exists or not - ruby-on-rails

I want to determine that an input field with id="foo" exists:
<input id="foo" ... />
And I also want to ensure that under certain conditions another input field with id="bar" does not exist.

Exists:
expect(page).to have_css('#bar')
Doesn't exist:
expect(page).to have_no_css('#bar')
Note: Don't use expect(page).to_not have_css, as that will wait for your element to appear.
An explanation of expect and negative forms like has_no_selector? and not has_selector? can be found in Capybara's Asynchronous JavaScript documentation.

To determine that a particular input field exists, use:
assert has_xpath?("//input[#id='foo']")
To determine that a particular input field does not exist, use one of:
assert has_no_xpath?("//input[#id='bar']")
refute has_xpath?("//input[#id='bar']")
Search for has_xpath in these Capybara node matcher docs.

Related

How to get placeholder value using assert_selector in rails

How do I get the placeholder value from an input bar using assert_selector in rails ?
<input placeholder="hello world" value="<%= params[:query] %>" required>
I want to check is placeholder has hello in it
While the answer by Lam Phan does answer the question, resorting to writing XPath queries when CSS has what you need isn't usually the best idea from a readability/understandability perspective.
CSS has a number of attribute selectors, the most useful for testing usually being
= matching
*= containing
^= begins with
~= whitespace separated matching
You can see the full set at https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors
In this case that means you could do any of
assert_selector('input[placeholder*="hello"]') # contains 'hello'
assert_selector('input[placeholder~="hello"]') # contains the word 'hello'
assert_selector('input[placeholder^="hello"]') # starts with 'hello'
Another option would be take advantage of the fact that the Capybara :field selector has a placeholder filter - https://github.com/teamcapybara/capybara/blob/master/lib/capybara/selector.rb#L34 - which takes a regex - so you could do
assert_field(placeholder: /hello/)
which is the same as
assert_selector(:field, placeholder: /hello/)
you could use xpath and verify that there's an input element whose's placeholder contains 'hello'
assert_selector(:xpath, './/input[contains(#placeholder,"hello")]')
if you want to check exactly an input with id
assert_selector(:xpath, './/input[#id="input_id"][contains(#placeholder,"hello")]')
im not sure there's a helper method that check regex something like ~= /.*hello.*/, if you want to do that, you still have another choice
placeholder = find('#input_id')['placeholder'] # or use :xpath
assert_match /.*hello.*/, placeholder

How do I display the text of a html span tag in a capybara test

I am running the following integration test on ruby on rails capybara.
test "displays correct date" do
assert page.has_content? #item.begining_date.strftime("%B %d")
end
I get false expected truthy. To try and debug this I want to see what is actually being displayed in the page during tests because I get the proper date when I run the website on my local host. I know that the html tag that displays the dates for the items have and id called date1, date2, date3, and so on.
like in the following example.
<span id="date1">Fri, June 12</span>
I want to display on my console/terminal what is in the span tags with id = "date1", id = "date2",...etc. So that when I run the tests I know what is actually being displayed instead of the expected content.
If you change your rspec assertion to
assert page.has_selector? '#date1', text: 'what you expect the text to be'
Then the error message when the test fails will indicate that the selector '#date1' was found but instead of the text you expected, it contains 'some other text'. This way you will know what was actually on the page.
The root cause of your issue is that you should never use raw assert with Capybara methods. If you instead use the assertions provided by Capybara you'll get error messages that give you useful information instead of "expected true got false"
assert_content #item.begining_date.strftime("%B %d")
will output what the content of the page is if it doesn't match
assert_selector '#date1', text: #item.begining_date.strftime("%B %d")
will output the contents of the element with id 'date1' if it doesn't match the provided text option.
If you're ever writing assert <any_capybara_provided_predicate>?... you're doing something wrong.

How to test file attachment on hidden input using capybara?

I have hidden input inside of label:
<label for="upload">
<input class="hidden" type="file" name="file[picture]">
</label>
When I click on the label, I attach a file and then confirm.
After that modal window pops up and I need to find appropriate div class.
How can I test this with the help of capybara?
Update: Capybara 2.12 added a make_visible option to attach_file so if using 2.12+ you can first try
attach_file('file[picture]', 'path/to/file.png', make_visible: true)
before directly using execute_script yourself
File inputs are a special case since they are so often hidden for styling reasons and use a system modal for interaction. Capybara makes it hard to fill in hidden fields on a page because users generally can't interact with them, so for file inputs normal practice is to use execute_script to make them visible and then fill them in.
execute_script("$('input[name=\"file[picture]\"]').removeClass('hidden')") # assumes you have jQuery available - if not change to valid JS for your environment
attach_file('file[picture]', 'path/to/file.png') # takes id, name or label text of field not a random selector
Using Capybara '2.7.1':
attach_file('file[picture]', 'path/to/file.png', visible: false)
You can do something along the lines of:
find('label[for=upload]').click
attach_file('input[name="file[picture]"]'), 'path/to/file.png')
within '.modal-popup' do
expect(page).to have_content '.divclass'
end

How to test for a target="_blank" attribute with Capybara?

I'm trying something which I thought would be simple. I need to modify a link to have the target="_blank" attribute and I would like to have a test to confirm that it's actually on the page. I've tried a ton of variations, the closest I can get is:
it { should have_link('change', href: 'url', target: '_blank') }
but that just throws an error saying that 'target:' is an invalid key. Is there a way to test for this attribute? Moreover, is there a general method for testing for HTML element attributes? The information I've found isn't clear.
Using Capybara 2.1.0, Rails 4.0.5.
Thanks
You can do what you want, or test for any attribute value, using have_selector and the CSS selector syntax for specifying attribute values, like this:
it { should have_selector('a[href="url"][target="_blank"]') }
It can't be done with have_link, since have_link
doesn't take any HTML attribute as an option (it takes the options that have_selector takes, plus :href), and
doesn't let you specify the entire selector.

cucumber/webrat: how to test if a submit button is not disabled

Just starting to use cucumber with webrat. I have these feature steps:
When /^I choose a DVD$/ do
#just click the first one we see
check("optional-dvds[]")
end
Then /^I should be able to place my order$/ do
#the place my order button should be clickable
end
The button in question has this html:
<input disabled="disabled" id="submit_button" name="commit" type="submit" value="Please send this DVD">
and, when the user clicks on a dvd, some js runs and removes the disabled attribute from the button. So, the second step needs to check that it doesn't have an attribute "disabled" after doing the previous step. How do i test this? I can think of one way, of using xpath and checking that a disabled commit button doesn't exist on the page, but i'd rather do something more explicit (actually, more jquery-esqu) along the lines of (pseudocode)
$("#submit_button").attr("disabled").should be_false
or something along these lines. I know this is a horrible mashup of jquery and rspec btw :)
Try this one
page.should have_no_xpath "//input[#id='submit_button' and #disabled]"
or this one
page.should have_no_selector "#submit_button", :disabled => 'disabled'

Resources