174

I have a field with a proper label that I can fill in with capybara without a problem:

fill_in 'Your name', with: 'John'

I'd like to check the value it has before filling it in and can't figure it out.

If I add after the fill_in the following line:

find_field('Your name').should have_content('John')

That test fails, although the filling just before worked as I've verified by saving the page.

What am I missing?

Rimian
  • 36,864
  • 16
  • 117
  • 117
Marc-André Lafortune
  • 78,216
  • 16
  • 166
  • 166

6 Answers6

362

Another pretty solution would be:

page.should have_field('Your name', with: 'John')

or

expect(page).to have_field('Your name', with: 'John')

respectively.

Also see the reference.

Note: for disabled inputs, you'll need to add the option disabled: true.

Marc-André Lafortune
  • 78,216
  • 16
  • 166
  • 166
fqxp
  • 7,680
  • 3
  • 24
  • 41
  • 28
    Much better than the selected answer! – Agent47DarkSoul Nov 17 '13 at 17:09
  • 3
    I would still prefer the selected answer because the error message shows you the expected and actual strings. This gives the unhelpful "expected field "my field" to return something" error. But this one does definitely read better and follows the page matcher API better. Upvotes all around!!! – mraaroncruz Jan 21 '14 at 15:09
  • This worked for me when using typeahead.js to verify the contents of the field, while the xpath matcher did not. – Avi Tevet Mar 26 '14 at 06:18
  • I think that happens because with that have_field capybara is waiting some time for that field before reporting failure. – roman-roman Apr 16 '14 at 12:47
  • 1
    As far as I can tell, this doesn't actually confirm the value of the field, just the presence of the field regardless of value. I'm guessing it's a bug since the docs say it should filter based on value. – Nick Jun 04 '14 at 20:52
  • 1
    Passing in `with` definitely only returned true if the value matches, for me, which is the expected result. – Ben Saufley Jul 21 '14 at 21:50
  • 4
    Maybe the error message has been improved since the answer was first written, but I now get `expected […] but there were no matches. Also found "", which matched the selector but not all filters..` on an empty field which comes very close to a very nice error message. – Patru Dec 25 '14 at 02:43
  • If you're using poltergeist, this answer is best because it will keep checking until the configured timeout, so you don't need a bunch of lame sleeps in your specs. – pduey Jun 03 '16 at 20:09
  • 1
    One more thing to look out for - if you field is disabled, you must do `expect(page).to have_field('Your name', with: 'John', disabled: true)` for this to work. – mahi-man Jun 27 '16 at 08:29
  • This has the advantage of being DOM-agnostic. It works for other form fields like `textarea`. – David Cook Mar 17 '21 at 03:38
196

You can use an xpath query to check if there's an input element with a particular value (e.g. 'John'):

expect(page).to have_xpath("//input[@value='John']")

See http://www.w3schools.com/xpath/xpath_syntax.asp for more info.

For perhaps a prettier way:

expect(find_field('Your name').value).to eq 'John'

EDIT: Nowadays I'd probably use have_selector

expect(page).to have_selector("input[value='John']")

If you are using the page object pattern(you should be!)

class MyPage < SitePrism::Page
  element :my_field, "input#my_id"

  def has_secret_value?(value)
    my_field.value == value
  end
end

my_page = MyPage.new

expect(my_page).to have_secret_value "foo"
Малъ Скрылевъ
  • 16,187
  • 5
  • 56
  • 69
DVG
  • 17,392
  • 7
  • 61
  • 88
  • 1
    Ah, I was missing the `.value` bit. Thanks! – Marc-André Lafortune May 08 '12 at 18:02
  • I was having the same problem, but with a div rather than a form field. For anybody else having the same problem, use find_by_id().text rather than find_field().value. It took me *ages* to spot that value only worked on form fields… – John Y Sep 08 '12 at 14:40
  • 9
    The problem with the latter way is that it does not use Capybara's polling cycle and therefore will fail instantly if the field is set by longer-running JS code. The first way is to be preferred unless you are trying this on a statically generated form. – fqxp May 16 '13 at 10:07
  • 1
    I think @fqxp has a better answer which uses RSpec Matchers and the new expectation syntax. From what I see in the documentation, `find_field` and other `Node::Finders` are used to find nodes and perform actions on them rather than expectation. Of course this is not a rule, but for something simple as this going with the inbuilt solution is a better idea. Just saying! – Agent47DarkSoul Nov 17 '13 at 17:08
  • True, expect would be the preferred way now, however that syntax was released about a month after this question. – DVG Nov 22 '13 at 14:35
  • You are a saviour!Thanks for the perfect answer. – PriyankaK Mar 11 '14 at 15:05
  • With **Minitest** the lines look like this: `assert has_xpath?("//input[@value='John']")` and `assert_equal 'John', find_field('Your name').value` – user664833 May 21 '14 at 22:16
  • You could also use the form `find_field('field-name').value.should have_content('John')` if you don't want to match on the entire field value. – siannopollo Jun 16 '15 at 16:42
3

If you specifically want to test for a placeholder, use:

page.should have_field("some_field_name", placeholder: "Some Placeholder")

or:

expect(page).to have_field("some_field_name", placeholder: "Some Placeholder")

If you want to test the user-entered value:

page.should have_field("some_field_name", with: "Some Entered Value")
Jim Stewart
  • 16,964
  • 5
  • 69
  • 89
1

I was wondering how to do something slightly different: I wanted to test whether the field had some value (while making use of Capybara's ability to re-test the matcher until it matches). It turns out that it's possible to use a "filter block" to do this:

expect(page).to have_field("field_name") { |field|
  field.value.present?
}
jonleighton
  • 1,041
  • 8
  • 12
1

If the field is a hidden one with an id of 'some_field', then you can use

expect(find("input#somefield", :visible => false).value).to eq 'John'
Obromios
  • 15,408
  • 15
  • 72
  • 127
0

This the easiest way:

expect(page).to have_field("name", with: "your name")
<input type="text" id="name" />
James Risner
  • 5,451
  • 11
  • 25
  • 47
adriannicolai
  • 11
  • 1
  • 2