selenium webdriver中有关隐藏元素的处理

太阳底下,所有隐藏的都能找出来。

问题描述

在某些场景下,UI界面需要隐藏某些元素,这些元素对用户来说不可见,但是依然存在HTML中,当然,对用户不可见的元素,对于selenium也是不可见的,因为selenium基本就是在模拟着用户的页面行为。

被隐藏的元素,会带有类似如下的CSS值:

style=”Display:none;"
style="visibility:hidden;"
type=”hidden”
……

针对这种情况,解决的思路有两个:

  • 使用Selenium WebDriver 中driver的execute_script method直接对元素进行操作,比如click
  • 使用selenium WebDriver 中driver的execute_script method修改元素的属性,让它可见,然后再进行操作

第二种显得有点绕弯了,而且第二种在某些情况下并不适用,比如:

看这段HTML代码:

<div class="ant-time-picker-panel-select">
  <ul>
    <li>09</li>
    <li>10</li>
    <li>11</li>
    <li>12</li>
    <li>13</li>
    <li>14</li>
    <li>15</li>
    <li>16</li>
    <li class="ant-time-picker-panel-select-option-selected">17</li>
  </ul>
</div>

这里其实并没有给元素添加一些不可见的CSS设置,即使你给13对应的li tag添加style="visibility:visible;" 也没有效果,依然是不可见。

通常的用户行为是将光标放在17的位置,然后鼠标滑动到最上方,让所有选项可见,然后再选择,为了不让问题过于复杂,针对隐藏元素,建议直接采用第一种解决方法。

解决方法

直接以上面的问题为例,假定我们需要选择13,先定位到13,采用cssSelector方式【戳这里了解如何快速获取xpath和cssSelector】:

element = driver.find_element(:css, ".ant-time-picker-panel-select > ul > li:nth-child(5)")

然后调用execute_script:

driver.execute_script("arguments[0].click();", element )

完成。

这里如果选定的值是一个变量呢?可以直接封装起来:

def select_hour(driver, hour)
  hour_list = driver.find_element(:css, ".ant-time-picker-panel-select > ul > li")
  target = hour_list.select {|x| x.text == hour }
  driver.execute_script("arguments[0].click();", target.first ) if target != []
end

OK,大功告成。

参考

Hidden Elements In HTML Page

docs for Selenium::WebDriver::Driver

PS. 还有一些麻烦的定位,比如从日期选择器中选定特定日期,可以参考How to Select Date from DatePicker in Selenium Webdriver,不过日期选择这种还是要具体问题具体分析。