75

I’m writing a cucumber test where I want to get the HTML in an element.

For example:

within 'table' do
  # this works
  find('//tr[2]//td[7]').text.should == "these are the comments" 

  # I want something like this (there is no "html" method)
  find('//tr[2]//td[7]').html.should == "these are the <b>comments</b>" 
end

Anyone know how to do this?

messivanio
  • 2,089
  • 16
  • 24
Jon Kruger
  • 3,831
  • 4
  • 30
  • 46

10 Answers10

67

You can call HTML DOM innerHTML Property:

find('//tr[2]//td[7]')['innerHTML']

Should work for any browser or driver. You can check all available properties on w3schools

llighterr
  • 864
  • 6
  • 4
26

This post is old, but I think I found a way if you still need this.

To access the Nokogiri node from the Capybara element (using Capybara 1.0.0beta1, Nokogiri 1.4.4) try this:

elem = find('//tr[2]//td[10]')
node = elem.native
#This will give you a Nokogiri XML element

node.children[1].attributes["href"].value.should == "these are the <b>comments</b>"

The last part may vary for you, but you should be able to find the HTML somewhere in that node variable

messivanio
  • 2,089
  • 16
  • 24
Eric Hu
  • 17,470
  • 8
  • 49
  • 67
19

In my environment, find returns a Capybara::Element - that responds to the :native method as Eric Hu mentioned above, which returns a Selenium::WebDriver::Element (for me). Then :text gets the contents, so it could be as simple as:

results = find(:xpath, "//td[@id='#{cell_id}']")
contents = results.native.text

if you're looking for the contents of a table cell. There's no content, inner_html, inner_text, or node methods on a Capybara::Element. Assuming people aren't just making things up, perhaps you get something different back from find depending on what else you have loaded with Capybara.

messivanio
  • 2,089
  • 16
  • 24
Steve
  • 727
  • 9
  • 13
12

Looks like you can do (node).native.inner_html to get the HTML content, for example with HTML like this:

<div><strong>Some</strong> HTML</div>

You could do the following:

find('div').native.inner_html
=> '<strong>Some</strong> HTML'
Tobias Cohen
  • 19,480
  • 7
  • 51
  • 51
6

I ran into the same issue as Cyril Duchon-Doris, and per https://github.com/teampoltergeist/poltergeist/issues/629 the way to access the HTML of an Capybara::Poltergeist::Node is via the outerHTML property, e.g.:

find('//tr[2]//td[7]')['outerHTML']
Geoff The
  • 71
  • 1
  • 1
4

Most of the other answers work only in Racktest (as they use Racktest-specific features).

If your driver supports javascript evaluation (like Selenium) you can use innerHTML :

html = page.evaluate_script("document.getElementById('my_id').innerHTML")
Andrei Botalov
  • 19,298
  • 8
  • 82
  • 117
1

If you're using the Poltergeist driver, these methods will allow you to inspect what matches:

http://www.rubydoc.info/gems/poltergeist/1.5.1/Capybara/Poltergeist/Node

For example:

page.find('[name="form-field"]').native.value == 'something'
Rimian
  • 32,654
  • 13
  • 106
  • 109
1

try calling find('//tr[2]//td[10]').node on it to get at the actual nokogiri object

0

You could also switch to capybara-ui and do the following:

# define your widget, in this case in your role
class User < Capybara::UI::Role
  widget :seventh_cell, [:xpath, '//tr[2]//td[7]']
end

# then in your tests
role = User.new

expect(role.widget(:seventh_cell).html).to eq(<h1>My html</h1>)
steel
  • 10,128
  • 6
  • 58
  • 91
0

Well, Capybara uses Nokogiri to parse, so this page might be appropriate:

http://nokogiri.org/Nokogiri/XML/Node.html

I believe content is the method you are looking for.

Steve Ross
  • 4,087
  • 1
  • 25
  • 38
  • 1
    There is no comment method... tried to do this: `find('//tr[2]//td[10]').content` – Jon Kruger Nov 05 '10 at 12:32
  • Can you post your actual step? It would be helpful to see what you are doing here. I've done page.find(...) and referred to the Nokogiri documentation to parse the response. Maybe I was just lucky... Note that I said page.find. I think Capybara provides the page object where Webrat provided the response object. – Steve Ross Nov 05 '10 at 17:28
  • The contents of the step are in the original post. – Jon Kruger Nov 12 '10 at 14:38
  • `inner_html()` should give you everything within a given node. `inner_text()` should give you all the text inside the node. – Steve Ross Nov 12 '10 at 18:57