Search code examples
rubyautomated-testswatirwatir-webdriver

Simulating a nested link click with 'watir-webdriver'


I'm working with the following HTML to simulate link click with 'watir-webdriver' which is nested inside

<li>
<div class="drop-head">
<ul>
    <li>
        <a href="#hotel" aria-label="go to Hotels" title="Hotels">Hotels</a>
    </li>
.....
</ul>
</div>

My script is very basic:

require 'watir-webdriver'

browser = Watir::Browser.new :firefox
browser.goto "https://www.acme,com/reserve"
wait = Selenium::WebDriver::Wait.new(:timeout => 5)

menu = browser.div(:class => "drop-head").li.a(:href => "#hotel").click

In the console I'm seeing the following error :

C:/apps/Ruby23/lib/ruby/gems/2.3.0/gems/watir-webdriver-0.9.9/lib/watir-webdriver/elements/element.rb:536:in `assert_element_found': unable to locate element, using {:href=>"#hotel", :tag_name=>"a"} (Watir::Exception::UnknownObjectException)
        from C:/apps/Ruby23/lib/ruby/gems/2.3.0/gems/watir-webdriver-0.9.9/lib/watir-webdriver/elements/element.rb:508:in `assert_exists'
        from C:/apps/Ruby23/lib/ruby/gems/2.3.0/gems/watir-webdriver-0.9.9/lib/watir-webdriver/elements/element.rb:114:in `click'
        from script4.rb:7:in `<main>'

Any help on this?


Solution

  • The problem is likely an over specification of the element's path. When you do:

    menu = browser.div(:class => "drop-head").li.a(:href => "#hotel").click
    

    It actually finds the first matching "drop-head" div and within that the first li element. Given that each link is likely in its own li element, you will only ever find the first link. For example in:

    <div class="drop-head">
      <ul>
        <li>
          <a href="#hotel" aria-label="go to Hotels" title="Hotels">Hotels</a>
        </li>
        <li>
          <a href="#restaurants" aria-label="go to Restaurants" title="Restaurants">Restaurants</a>
        </li>
      </ul>
    </div>
    

    Looking for the second link, "#restaurants":

    browser.div(:class => "drop-head").li.a(:href => "#restaurants")
    

    Will actually be looking for the link in the first li element:

    <li>
     <a href="#hotel" aria-label="go to Hotels" title="Hotels">Hotels</a>
    </li>
    

    The solution is to only specify the element's path when actually necessary to differentiate the element. Assuming there is only one link with that href, you can probably just do:

    browser.a(:href => "#hotel").click