所以我有一个包装WebElement的类,并添加了一些功能,使它在我的页面对象中更有用。我现在需要设置文本输入的文本,我能看到的唯一方法就是注入javascript来查找元素并设置其value属性。
对于我有一个id要关闭的简单情况,这很简单,但是如果有动态生成的表单,可能没有一个有用的ID可以去掉 - 其中一些是通过找到封闭的表单然后找到的在其中寻找一个css选择器,其他输入匹配其他形式的同一个css选择器。
我可以看到我可以通过xpath找到所有内容来解决这个问题,但是必须有一个不那么脆弱/破坏性的解决方案。我知道你可以从Javascript执行器获取一个WebElement,我想知道是否可以向给定的WebElement注入javascript对象引用,如果没有,可以从现有的WebElement中获取运行时唯一的xpath
我正在使用python,但其他语言的解决方案可能是可转移的。
我知道某处有一个webdriver元素缓存,我可以在该缓存中获取一个元素的id:
有没有办法在注入的javascript中使用它?
答案 0 :(得分:3)
如果我正确理解您的问题,您就会问如何将Selenium WebElement对象传递给JavaScript。如果被测试的页面使用的是jQuery,它可能如下所示:
# select the element in python
form1 = driver.find_element_by_id('id_of_the_form')
# execute javascript which references the object
execute_script("$(arguments[0]).find('input.childOfInterest').val('newValue')", form1)
因为execute_script()
接受String(JS执行)和可选的第二个参数(对象引用),所以使用arguments[0]
引用对象(在本例中为WebElement)。在这个例子中,我传入了父表单元素,然后使用jQuery选择表单,使其成为一个jQuery对象,然后调用jQuery的.find()
,传入一个css选择器来定位子元素,然后调用jQuery的.val()
来更新元素的值。
您还询问了如何在运行时生成xpath。 以下是此示例(完整答案here):
// javascript
function getPathTo(element) {
if (element.id!=='')
return 'id("'+element.id+'")';
if (element===document.body)
return element.tagName;
var ix= 0;
var siblings= element.parentNode.childNodes;
for (var i= 0; i<siblings.length; i++) {
var sibling= siblings[i];
if (sibling===element)
return getPathTo(element.parentNode)+'/'+element.tagName+'['+(ix+1)+']';
if (sibling.nodeType===1 && sibling.tagName===element.tagName)
ix++;
}
}
以下是在Selenium中实施它的步骤
# define xpath generation JS in python
xpathJS = "function getPathTo(element){ if(element....."
# add new function to the page
execute_script(xpathJS)
# select an element with SE
element1 = driver.find_element_by_id('id_of_element')
# get the xpath of the element
xpath1 = execute_script("return getPathTo(arguments[0])", element1)