ruby-on-railsrspeccapybara

Capybara: click on element found by the icon class


I would like to check that, when click an icon link, the current_path is the path of the 'show' action.

So, given this HTML:

<a class="btn btn-xs" href="/admin/hotels/1">
   <i class="fa fa-eye fa-lg"></i>
</a>

And this capybara test:

describe "GET /hotels", js:true do
  before :each do
    @hotel = create(:hotel)
    visit admin.hotels_path
  end
  it "eye icon links to show" do
    find(:css, 'i.fa.fa-eye.fa-lg').find(:xpath,".//..").click
    expect(current_path).to eq(admin.hotel_path(@hotel))
  end
end

I receive this error message:

   1) Hotels index hotel creation GET /hotels eye icon link to show
      Failure/Error: expect(current_path).to eq(admin.hotel_path(@hotel))

   expected: "/admin/hotels/560bb674467261c7a4000002"
        got: "/admin/hotels"

I deduce that find(:css, 'i.fa.fa-eye.fa-lg').find(:xpath,".//..").click is not working as I expect.

The execution of find(:css, 'i.fa.fa-eye.fa-lg').find(:xpath,".//..") is returning:

=> #<Capybara::Element tag="a">

Am I doing something wrong?


Solution

  • The reason the test fails with :js is because clicking the link does only that. It doesn't wait for the results of the click (loading the new page). Because of that calling current_path immediately after still gets the original path. Removing the :js stops using poltergeist and instead uses rack-test which is synchronous but lacks a lot of real browser behavior. In capybara 2.4 you would have needed to check for content that would be on the show page and once that appeared then get the current path, however capybara 2.5 has the have_current_path matcher which will utilize capybaras waiting behavior. Also there is no need to click on the a element, clicking on its contents like a user would do should work just fine. So

    find(:css, 'i.fa.fa-eye.fa-lg').click
    expect(page).to have_current_path(admin.hotel_path(@hotel))
    

    should work both with and without :js