简体   繁体   中英

How to select an inline element using watir in ruby

I want the text "HEATMAPS" to be clicked after the webpage is opened. I have tried number of click methods, including recognizing as hyperlink, as text, as using xpath etc. None of them worked. I feel, I am either misunderstanding the links, as to be a hyperlink or choosing a wrong xpath.

Link of the web page

PFB the code below

 require 'watir-webdriver'
 require 'watir-ng'
 WatirNg.patch!
 WatirNg.register(:ng_scope).patch!
 browser = Watir::Browser.new
 browser.goto 'http://app.vwo.com/#/campaign/108/summary?   token=eyJhY2NvdW50X2lkIjoxNTA3MzQsImV4cGVyaW1lbnRfaWQiOjEwOCwiY3JlYXRlZF9vbiI6MTQ0NDgxMjQ4MSwidHlwZSI6ImNhbXBhaWduIiwidmVyc2lvbiI6MSwiaGFzaCI6IjJmZjk3OTVjZTgwNmFmZjJiOTI5NDczMTc5YTBlODQxIn0='

 lin = browser.link :text=> 'HEATMAPS'
 lin.exist?
 lin.click

Can someone please guide me on this, as to how I can make that link with the text "HEATMAPS" in the page get clicked.

The error i get:

`This code has slept for the duration of the default timeout waiting for an Element to exist. If the test is still passing, consider using Element#exists? instead of rescuing UnknownObjectException
C:/Ruby22/lib/ruby/gems/2.2.0/gems/watir-6.1.0/lib/watir/elements/element.rb:507:in `rescue in wait_for_exists': timed out after 30 seconds, waiting for {:text=>"HEATMAPS", :tag_name=>"a"} to be located (Watir::Exception::UnknownObjectException)
        from C:/Ruby22/lib/ruby/gems/2.2.0/gems/watir-6.1.0/lib/watir/elements/element.rb:497:in `wait_for_exists'
        from C:/Ruby22/lib/ruby/gems/2.2.0/gems/watir-6.1.0/lib/watir/elements/element.rb:515:in `wait_for_present'
        from C:/Ruby22/lib/ruby/gems/2.2.0/gems/watir-6.1.0/lib/watir/elements/element.rb:533:in `wait_for_enabled'
        from C:/Ruby22/lib/ruby/gems/2.2.0/gems/watir-6.1.0/lib/watir/elements/element.rb:656:in `element_call'
        from C:/Ruby22/lib/ruby/gems/2.2.0/gems/watir-6.1.0/lib/watir/elements/element.rb:114:in `click'
        from C:/Users/Mrityunjeyan/Documents/GitHub/Simpleprograms/webautomation.rb:10:in `<main>'`

This would display me the inner_html text but still wouldnt click

lin = browser.span(:class => 'ng-scope').inner_html puts lin

The problem is that the link's text is not "HEATMAPS". It is actually "Heatmaps". The text locator is case-sensitive, which means you need:

lin = browser.link :text=> 'Heatmaps'

You can see this if you inspect the HTML:

<a ui-sref="campaign.heatmap-clickmap" href="#/analyze/analysis/108/heatmaps?token=eyJhY2NvdW50X2lkIjoxNTA3MzQsImV4cGVyaW1lbnRfaWQiOjEwOCwiY3JlYXRlZF9vbiI6MTQ0NDgxMjQ4MSwidHlwZSI6ImNhbXBhaWduIiwidmVyc2lvbiI6MSwiaGFzaCI6IjJmZjk3OTVjZTgwNmFmZjJiOTI5NDczMTc5YTBlODQxIn0%3D">
  <!-- boIf: isAnalyticsCampaign -->
  <span bo-if="isAnalyticsCampaign" class="ng-scope">Heatmaps</span>
  <!-- boIf: !isAnalyticsCampaign -->
</a>

It only looks like "HEATMAPS" due to the styling. One of the styles includes a text-transform: uppercase; which visually capitalizes the text. Watir does not interpret the styles, so only knows that the text node is "Heatmaps".

Once you have identified the link, clicking still has a problem:

lin.click
#=> Selenium::WebDriver::Error::UnknownError:
#=> unknown error: Element <a ui-sref="analyze.heatmaps" ng-class="{selected: (locationContains('analyze', 'heatmap') &amp;&amp; !locationContains('analyze', '/analysis') &amp;&amp; state.current.name !== 'campaign.heatmap-clickmap') || (isAnalyzeHeatmapEnabled &amp;&amp; (isAnalyzeDeprecatedHeatmapView || locationContains('analyze', '/analysis', 'heatmaps')) )}" data-qa="nav-main-analyze-heatmap" href="#/analyze/heatmap">...</a>
#=> is not clickable at point (90, 121).
#=> Other element would receive the click: <div ng-show="!isCROSetupView" class="">...</div>

The link being located is actually the one in the left menu, which is disabled, rather than the top menu. You need to scope the link locator to just the top menu. Using the parent ul element appears to be sufficient:

lin = browser.ul(class: 'page-nav').link(text: 'Heatmaps')
lin.click

To see the click complete, you might want to tell Chrome not to close at the end of the script. This is done by opening the browser using the following option:

caps = Selenium::WebDriver::Remote::Capabilities.chrome("chromeOptions" => {'detach' => true})
browser = Watir::Browser.new :chrome, desired_capabilities: caps

Your target link doesn't have any text . I confirmed with nokogiri that the text of the <a> tag includes the text inside the child <span> tag, and it turns out Watir works the same way.

If you use a Chrome browser, you can select:

View > Developer > Developer tools

Then you can select an element on the page, and the corresponding section in the html will be highlighted. Here is what the html looks like:

<a ui-sref="campaign.heatmap-clickmap" 
   href="#/analyze/analysis/108/heatmaps?token=eyJhY2NvdW50X2lkIjoxNTA3MzQsImV4cGVyaW1lbnRfaWQiOjEwOCwiY3JlYXRlZF9vbiI6MTQ0NDgxMjQ4MSwidHlwZSI6ImNhbXBhaWduIiwidmVyc2lvbiI6MSwiaGFzaCI6IjJmZjk3OTVjZTgwNmFmZjJiOTI5NDczMTc5YTBlODQxIn0%3D"> 
<!-- boIf: isAnalyticsCampaign -->

<span bo-if="isAnalyticsCampaign" class="ng-scope">Heatmaps</span> 

<!-- boIf: !isAnalyticsCampaign --> </a>

The basic structure is:

<a><span>Heatmaps</span></a>

Chrome even has a feature where you can right click on an element and get its xpath, which you can use with Watir.

However, when I execute my program to go to that page, I see Chrome launch, and then I'm presented with a login page rather than the page that was presented to me at your link.

Arghhh...what a colossal waste of time. I thought Watir must be broken. With the proper url, I can get the link using several different techniques:

1)

require 'watir'
require 'watir-ng'   #<=NOTE THIS

WatirNg.register(:'bo_if').patch!  #<= NOTE THIS

br = Watir::Browser.new :chrome
br.goto 'http://app.vwo.com/#/analyze/analysis/108/summary?token=eyJhY2NvdW50X2lkIjoxNTA3MzQsImV4cGVyaW1lbnRfaWQiOjEwOCwiY3JlYXRlZF9vbiI6MTQ0NDgxMjQ4MSwidHlwZSI6ImNhbXBhaWduIiwidmVyc2lvbiI6MSwiaGFzaCI6IjJmZjk3OTVjZTgwNmFmZjJiOTI5NDczMTc5YTBlODQxIn0%3D'

target_link = br.span(
  class: 'ng-scope',
  'bo_if': 'isAnalyticsCampaign', 
).parent  #<= NOTE THIS

puts target_link.text  #HEATMAPS
puts target_link.href  #http://app.vwo.com/#/analyze/analysis/1.....

2)

require 'watir'
require 'watir-ng'  #<=NOTE THIS

WatirNg.register(:ui_sref).patch!  #<=NOTE THIS

br = Watir::Browser.new :chrome
br.goto 'http://app.vwo.com/#/analyze/analysis/108/summary?token=eyJhY2NvdW50X2lkIjoxNTA3MzQsImV4cGVyaW1lbnRfaWQiOjEwOCwiY3JlYXRlZF9vbiI6MTQ0NDgxMjQ4MSwidHlwZSI6ImNhbXBhaWduIiwidmVyc2lvbiI6MSwiaGFzaCI6IjJmZjk3OTVjZTgwNmFmZjJiOTI5NDczMTc5YTBlODQxIn0%3D'

target_link = br.link(
  ui_sref: 'campaign.heatmap-clickmap',
  href: '#/analyze/analysis/108/heatmaps?token=eyJhY2NvdW50X2lkIjoxNTA3MzQsImV4cGVyaW1lbnRfaWQiOjEwOCwiY3JlYXRlZF9vbiI6MTQ0NDgxMjQ4MSwidHlwZSI6ImNhbXBhaWduIiwidmVyc2lvbiI6MSwiaGFzaCI6IjJmZjk3OTVjZTgwNmFmZjJiOTI5NDczMTc5YTBlODQxIn0%3D'
)

puts target_link.text   #HEATMAPS
puts target_link.href   #http://app.vwo.com/#/analyze/analysis/108...

3) Getting the xpath by right clicking on the link in Chrome:

require 'watir'

br = Watir::Browser.new :chrome
br.goto 'http://app.vwo.com/#/analyze/analysis/108/summary?token=eyJhY2NvdW50X2lkIjoxNTA3MzQsImV4cGVyaW1lbnRfaWQiOjEwOCwiY3JlYXRlZF9vbiI6MTQ0NDgxMjQ4MSwidHlwZSI6ImNhbXBhaWduIiwidmVyc2lvbiI6MSwiaGFzaCI6IjJmZjk3OTVjZTgwNmFmZjJiOTI5NDczMTc5YTBlODQxIn0%3D'

target_link = br.link(
  xpath: '//*[@id="main-container"]/ul/li[3]/a'
)
puts target_link.text  #HEATMAPS
puts target_link.href  #http://app.vwo.com/#/analyze/analysis/108....

xpath can handle any tag or attribute name, unlike Watir, so it seems like a good tool in that regard.

4) A less brittle xpath:

require 'watir'

br = Watir::Browser.new :chrome
br.goto 'http://app.vwo.com/#/analyze/analysis/108/summary?token=eyJhY2NvdW50X2lkIjoxNTA3MzQsImV4cGVyaW1lbnRfaWQiOjEwOCwiY3JlYXRlZF9vbiI6MTQ0NDgxMjQ4MSwidHlwZSI6ImNhbXBhaWduIiwidmVyc2lvbiI6MSwiaGFzaCI6IjJmZjk3OTVjZTgwNmFmZjJiOTI5NDczMTc5YTBlODQxIn0%3D'


a_href = "#/analyze/analysis/108/heatmaps?token=eyJhY2NvdW50X2lkIjoxNTA3MzQsImV4cGVyaW1lbnRfaWQiOjEwOCwiY3JlYXRlZF9vbiI6MTQ0NDgxMjQ4MSwidHlwZSI6ImNhbXBhaWduIiwidmVyc2lvbiI6MSwiaGFzaCI6IjJmZjk3OTVjZTgwNmFmZjJiOTI5NDczMTc5YTBlODQxIn0%3D"

target_link = br.link(
  xpath: %Q{ //a[@href="#{a_href}"] } +
               '[@ui-sref="campaign.heatmap-clickmap"]' +
               '[child::span[@class="ng-scope"][@bo-if="isAnalyticsCampaign"][text()="Heatmaps"]]' 
)

The xpath looks for an <a> tag with two attributes:

//a[@href="blah"][@ui-sref="bleh"]

which has a child <span> (ie a direct child) with three attributes:

[child::span[@class="blih"][@bo-if="bloh"][text()="Heatmaps"]]

After I programmatically click the link:

target_link.click

Watir goes to the next page.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM