0

In my Rails 3.2.16 app with a Bootstrap 2.3 navigation list, I want to write a test that confirms that a specific item is active and that it has the right icon. I'm using rspec 2.14.1 and capybara 2.1.0.

I assume the way to do this is with a capybara has_xpath test, but the classes that I need to check ("active" and "fa-folder-open") as well as the actual text ("Inbox") are at different levels of the HTML hierarchy.

Given this HTML:

<ul class="nav nav-list" role="navigation">
  <li class="active">
    <a href="/messages/my/inbox">
      <i class="fa fa-folder-open fa-fw">
      </i> Inbox</a>
  </li>
  <li class="">
    <a href="/messages/my/draft">
      <i class="fa fa-folder fa-fw">
      </i> Draft</a>
  </li>
</ul>

is there an XPath that will confirm that the link with text "Inbox" is "active" and has the "fa-folder-open" icon?

EDIT

I copied the example HTML above the XPath tester, where the Format button not only did some pretty formatting, it removed the closing </i> tags. The raw HTML isn't as pretty:

<ul class="nav nav-list" role="navigation">
  <li class="active">
    <a href="/messages/my/inbox">
      <i class="fa fa-folder-open fa-fw"></i> Inbox
</a>  </li>
  <li class="">
    <a href="/messages/my/draft">
      <i class="fa fa-folder fa-fw"></i> Draft
</a>  </li>
</ul>
Mark Berry
  • 17,843
  • 4
  • 58
  • 88

2 Answers2

0

Try with:

expect(page).to have_xpath("//li[contains(@class, 'active')//i[contains(text()='Inbox' and contains(@class, 'fa-folder-open')]")
carpamon
  • 6,515
  • 3
  • 38
  • 51
0

Nicolas' answer was helpful in suggesting that I use contains.

This SO answer helped me see that I can nest the brackets to find nested nodes.

With some trial and error at www.xpathtester.com, I came up with this XPath:

//li[contains(@class,'active') and a[text()=' Inbox' and i[contains(@class,'fa-folder-open')]]]

EDIT

My XPath above wasn't working on the raw HTML (see edited question). The XPath wasn't finding the " Inbox" text, probably due to the line breaks before the <\a> tags. With thanks to this answer's example of normalize-space() without the text() argument, this XPath works:

//li[contains(@class,'active') and a[normalize-space()='Inbox' and i[contains(@class,'fa-folder-open')]]]

Note that it must look for 'Inbox', not ' Inbox'. normalize-space() strips leading and trailing whitespace (including the line breaks that were causing problems), so the leading space must be removed from the text that it is looking for.

Community
  • 1
  • 1
Mark Berry
  • 17,843
  • 4
  • 58
  • 88