22

I am using ruby on rails 3.2.3 and capybara to help creating request spec. My goal is to create a spec request that test the log out. The web page:

<li class="dropdown">
  <a class="dropdown-toggle" data-toggle="dropdown">
    Welcome <%= current_user.first_name + " "+ current_user.last_name%>
    <b class="caret"></b>
  </a>
  <ul class="dropdown-menu">
    <a href="#">
      <%= link_to "Sign out", destroy_user_session_path, :method => :delete%>
    </a>
  </ul>
</li>

For the test, I have

describe "sign out" do
  it "should let user to sign out" do
    login_as user, :scope => :user
    # click_on "Welcome #{user.first_name} #{user.last_name}"
    # Now click on Sign out
  end
end

I don't know how to click on the Sign out using capybara because it is in a drop down menu, therefore not visible on page. Does anyone know ?

Is there any other way to click on an element in a dropdown menu ?

Bryan Ash
  • 4,385
  • 3
  • 41
  • 57
u19964
  • 3,255
  • 4
  • 21
  • 28
  • I have resolve the same issue (on Twitter Bootstrap button drop down menu) by select the specific link tag: `find('a', :text => option_title).click` – Frankovskyi Bogdan Mar 22 '13 at 18:49

5 Answers5

8

I've tested a dropdown just by clicking both links

click_link "Welcome #{current_user.first_name} #{current_user.last_name}"
click_link 'sub link'
DVG
  • 17,392
  • 7
  • 61
  • 88
  • How do you click_link "dropdown link". – u19964 Jun 30 '12 at 05:37
  • You of course may have to replace the variable current_user with the user object created for your test – DVG Jun 30 '12 at 21:08
  • Try running it with a JavaScript driver so you can see what is happening. I copied that directly out of my own project. – DVG Jul 01 '12 at 14:23
  • I don't get it. How to "run with a javascript driver". Sorry if my question is bad. thank you – u19964 Jul 01 '12 at 15:12
  • 2
    Change `it "my example" do` to `it "my example", js: true do`By default this will launch Firefox and run the example with selenium, so you can see it run. You might add a sleep to the end so you have time to take in what is happening – DVG Jul 01 '12 at 15:38
  • OK that make sense. I install selenium and tried but got error like this: expected there to be content "Welcome First Last" in "Internal Server Error\nSQLite3::BusyException: cannot rollback transaction - SQL statements in progress: rollback transaction\nWEBrick/1.3.1 – u19964 Jul 01 '12 at 16:16
  • So when selenium launch firefox, it got the content "Internal Server Error\nSQLite3::BusyException: cannot rollback transaction - SQL statements in progress: rollback transaction\nWEBrick/1.3.1 – u19964 Jul 01 '12 at 16:22
6

Hello I figured it out eventually. I had to use xpath to find the link. Based on the html above, here is what I did:

In rspec, I wrote:

page.find(:xpath, "//a[@href='/users/sign_out']").click

The reason I use "//a[@href='/users/sign_out']" is because the link_to "Sign out", destroy_user_session_path, :method => :delete is compiled to <a href="/users/sign_out" ... on the web page.

And it works :-)

Oh by the way, I found this useful link: http://www.suffix.be/blog/click_image_in_link_capybara

u19964
  • 3,255
  • 4
  • 21
  • 28
  • I've been able to test a very similar dropdown just by doing two clicks, one to open the dropdown and one to click the link. – DVG Jun 30 '12 at 01:58
  • 1
    That's what I thought too. Can you post some code ? It would be great if that can be applied to the html above. Thanks. – u19964 Jun 30 '12 at 02:32
  • I believe the missing piece here is enabling Javascript for the request spec; usually capybara-webkit (https://github.com/thoughtbot/capybara-webkit). Once this is enabled, then the clicks will work as your browser has them work. – Jesse Wolgamott Jun 30 '12 at 16:55
  • Hi, this way it actually works (the test is able to click) without enabling js. – u19964 Jul 01 '12 at 16:28
  • Finding via xpath gives you a lot more control than the `click_link` method referenced in these answers. This should have more up votes! – Starkers Feb 09 '14 at 15:02
4

A much easier solution is simply this:

select("option you want to select from menu", :from => "label name")

NOTE: The "label name" is the actual text of the <label>. However, you can also use the "id" or "name" attribute of the <select> here as well, which I think is better since you may change the label text at some point and if you do, your tests will still pass.

nfriend21
  • 2,170
  • 1
  • 21
  • 21
  • 2
    "select" does not work for non-html select box elements. Question is about "button drop down menu" (like twitter bootsrap one) which is not html select box. – Frankovskyi Bogdan Mar 22 '13 at 18:18
  • 2
    This answer actually addresses the title of the question. I guess that's why it has the most votes. – yuяi Jul 30 '13 at 21:03
  • 1
    The code isn't a select, it's bootstrap's logout code. So select won't work – netwire Aug 28 '13 at 02:32
2

I had a similar problem, but my dropdown didn't have any text, only icons:

%li#user-menu.dropdown
  %a.dropdown-toggle{ href: "#", data: { toggle: "dropdown" }, role: "button", aria: { haspopup: "true", expanded: "false" } }
    %i.fa.fa-user
    %span.caret
  %ul.dropdown-menu
    %li.logout-text= link_to "Log Out", destroy_user_session_path, :method => :delete

In my spec I used:

def when_I_sign_out
  find('#user-menu').click
  click_on 'Log Out'
end
Bryan Ash
  • 4,385
  • 3
  • 41
  • 57
1

My example for this

find("ol.nya-bs-select.btn-default.form-control[ng-model='scope.values.countries']")
    .find_button("Nothing selected").click
Ori Lentz
  • 3,668
  • 6
  • 22
  • 28
Den K
  • 11
  • 1