简体   繁体   中英

get javascript selector of WebElement

So I have a class that wraps a WebElement and adds functionality to make it more useful in my page objects. I now need to set the text of a text input, and the only way I can see to do this is to inject javascript to find the element and set its value attribute.

For simple cases where I have an id to go off, this is fairly simple, however where there are dynamically generated forms there might not be a useful id to go off - some of these are found by finding the enclosing form and then looking for a css selector within it, where there are other inputs matching the same css selector within other forms.

I can see that I could solve this by finding everything by xpath, however there must be a less brittle/disruptive solution. I know that you can get a WebElement from a Javascript executor, what I'm wondering is if it's possible to inject a javascript object reference to a given WebElement, and if not, a way to get a unique xpath at runtime from an existing WebElement.

I'm using python, but solutions in other languages would probably be transferrable.


Edit

I know that there is a webdriver element cache somewhere, and that I can get an element's id in that cache:

在此处输入图片说明

Is there any way of using this in the injected javascript?

If I understand your question correctly, you are asking how to pass a Selenium WebElement object to your JavaScript. If the page under test is using jQuery, it might look like this:

# 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)

Because execute_script() takes a String (JS to execute) and an optional second parameter (object reference), you then refer to the object (a WebElement in this case) using arguments[0] . In this example, I passed in the parent form element, and then used jQuery to select the form, making it a jQuery object, and then called jQuery's .find() off of that, passing in a css selector to locate the child element, and then called jQuery's .val() off of that to update the element's value.


You also asked how to generate an xpath at runtime. Here's an example of this (complete answer 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++;
    }
}

Here are steps to implement it in your 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)

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