如何 select 在 ruby 中使用 watir 的内联元素

How to select an inline element using watir in ruby

我希望在网页打开后点击文本 "HEATMAPS"。我尝试了多种点击方法,包括识别为 hyperlink、识别为文本、使用 xpath 等。其中 None 有效。我觉得,我要么误解了 links,认为它是 hyperlink,要么选择了错误的 xpath。

Link of the web page

PFB 下面的代码

 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

有人可以指导我吗,关于如何使页面中带有文本 "HEATMAPS" 的 link 获得点击。

我得到的错误:

`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>'`

这会向我显示 inner_html 文本,但仍然不会点击

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

您的目标 link 没有任何文本。我向 nokogiri 确认 <a> 标签的文本包含 child <span> 标签内的文本,结果 Watir 的工作方式相同。

如果您使用 Chrome 浏览器,您可以 select:

View > Developer > Developer tools

然后你可以select页面上的一个元素,html中的相应部分将被高亮显示。这是 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>

基本结构为:

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

Chrome 甚至还有一个功能,您可以右键单击一个元素并获取其 xpath,您可以将其与 Watir 一起使用。

但是,当我执行我的程序转到那个页面时,我看到 Chrome 启动,然后我看到一个登录页面,而不是在 link.

啊……真是浪费时间。 我以为 Watir 一定坏了。使用正确的 url,我可以使用几种不同的技术获得 link:

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) 通过右键单击 Chrome 中的 link 获取 xpath:

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 可以处理任何标签或属性名称,这与 Watir 不同,因此在这方面它似乎是一个很好的工具。

4) 不那么脆弱的 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"]]' 
)

xpath 查找具有两个属性的 <a> 标记:

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

其中有一个 child <span>(即直接 child),具有三个属性:

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

在我以编程方式单击 link 之后:

target_link.click

Watir 转到下一页。

问题是 link 的文本不是 "HEATMAPS"。实际上是"Heatmaps"。文本定位器是 case-sensitive,这意味着您需要:

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

如果你检查 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>

由于样式的原因,它只是看起来像 "HEATMAPS"。其中一种样式包括 text-transform: uppercase;,它在视觉上将文本大写。 Watir 不解释样式,所以只知道文本节点是 "Heatmaps".

一旦你确定了 link,点击仍然有问题:

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>

定位到的link实际上是左侧菜单中的那个,被禁用,而不是顶部菜单。您需要将 link 定位器的范围限制在顶部菜单。使用父 ul 元素似乎就足够了:

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

要看到 click 完成,您可能想告诉 Chrome 不要在脚本末尾关闭。这是通过使用以下选项打开浏览器来完成的:

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