太阳底下,所有隐藏的都能找出来。
问题描述
在某些场景下,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,大功告成。
参考
docs for Selenium::WebDriver::Driver
PS. 还有一些麻烦的定位,比如从日期选择器中选定特定日期,可以参考How to Select Date from DatePicker in Selenium Webdriver,不过日期选择这种还是要具体问题具体分析。