Running a Selenium driver to execute Javascript's elementFromPoint feature

I am currently working on integrating an "object picker" into my Selenium-based framework, a feature commonly found in many commercial automation tools. I have been using a Javascript command to locate the element at the mouse's current position, but for some reason, I am not getting the expected element.

When using ChromeDriver or InternetExplorerDriver, the script always returns the header object, regardless of the web page being viewed or the mouse position. Even though it seems like the script is fetching coordinates (0, 0) instead of the actual mouse position, I have double-checked and confirmed that Cursor.Position is providing the correct values.

On the other hand, when utilizing FirefoxDriver, I encounter an exception:

"Argument 1 of Document.elementFromPoint is not a finite floating-point value. (UnexpectedJavaScriptError)"

Could someone help me identify what mistake I might be making?

    private void OnHovering()
    {
        if (Control.ModifierKeys == System.Windows.Forms.Keys.Control)
        {
            IWebElement ele = null;
            try
            {
                // Locate the element at the mouse position
                if (driver is IJavaScriptExecutor)
                    ele = (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript(
                        "return document.elementFromPoint(arguments[0], arguments[1])", 
                        new int[] { Cursor.Position.X, Cursor.Position.Y });

                // Select the identified element
                if (ele != null)
                    SelectElement(ele);
            }
            catch (Exception) { }
        }
    }

Thank you in advance!

Answer №1

The key here lies in how you pass the coordinates into the script. Remember, when using ExecuteScript(), each script argument must be specified individually. The issue in your situation was that you only specified one argument x, causing it to assume that y should default to a value of 0, which typically corresponds to a header.

Instead of:

ele = (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript(
                        "return document.elementFromPoint(arguments[0], arguments[1])", 
                        new int[] { Cursor.Position.X, Cursor.Position.Y });

You should use:

ele = (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript(
                        "return document.elementFromPoint(arguments[0], arguments[1])", 
                        Cursor.Position.X, Cursor.Position.Y);

Answer №2

The provided code by alecxe is effective in most scenarios, however, it may encounter issues if the webpage contains frames or iframes.

To handle frames and iframes gracefully, a more extensive code solution is necessary.

/// <summary>
/// Retrieve the element at the specified viewport coordinates X, Y
/// </summary>
static public RemoteWebElement GetElementFromPoint(RemoteWebDriver driver, int X, int Y)
{
    while (true)
    {
        String script = "return document.elementFromPoint(arguments[0], arguments[1]);";

        RemoteWebElement element = (RemoteWebElement)driver.ExecuteScript(script, X, Y);
        if (element == null)
            return null;

        if (element.TagName != "frame" && element.TagName != "iframe")
            return element;

        Point position = GetElementPosition(element);
        X -= position.X;
        Y -= position.Y;

        driver.SwitchTo().Frame(element);
    }
}

/// <summary>
/// Get the top/left corner position of the Element within the document.
/// NOTE: RemoteWebElement.Location is based on the document's top and does not consider scroll position.
/// </summary>
static public Point GetElementPosition(RemoteWebElement element)
{
    String script = "var X, Y; "
                    + "if (window.pageYOffset) " 
                    + "{ "
                    + "  X = window.pageXOffset; "
                    + "  Y = window.pageYOffset; "
                    + "} "
                    + "else " 
                    + "{ "
                    + "  var elem = document.documentElement; "         
                    + "  if (!elem.clientHeight) elem = document.body; "
                    + "  X = elem.scrollLeft; "
                    + "  Y = elem.scrollTop; "
                    + "} "
                    + "return new Array(X, Y);";

    RemoteWebDriver driver = (RemoteWebDriver)element.WrappedDriver;
    IList<Object>   coordinates  = (IList<Object>)  driver.ExecuteScript(script);

    int scrollX = Convert.ToInt32(coordinates[0]);
    int scrollY = Convert.ToInt32(coordinates[1]);

    return new Point(element.Location.X - scrollX,
                     element.Location.Y - scrollY);
}

This functionality should be incorporated into WebDriver for enhanced performance.

Answer №3

I encountered a similar problem recently. Upon investigating, I discovered that the error was occurring due to the element I needed to locate being hidden (having the attribute display:none). Therefore, it did not have a specific location.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The feature of automatically selecting all text input content upon focus is not functioning properly in Microsoft Edge

I've encountered a specific issue with Microsoft Edge when trying to select all the text in an input field. My approach involves using Angular's ng-focus to trigger a function in the controller that selects the text in the field. function select ...

What are the steps for submitting a form with AJAX?

I am having trouble submitting a form via ajax. I am not receiving any error messages even though I have set up error handling throughout the website. Here is my code: <script type="text/javascript" src="jquery.js"></script> <div id="shower ...

What is the best way to incorporate auto refresh in a client-side application using vue.js?

Disclaimer: I have separated my client application (Vue.js) from the server side (DjangoRest). I am utilizing JWT for validating each request sent from the client to the server. Here is how it works - The client forwards user credentials to the server, an ...

Obtain the href attribute using Selenium in Python

I'm trying to extract all href links from the subelements within a parent class called search-content. The parent class contains divs with the class card-col, and within these divs, there is another div followed by an href link. I only want to retriev ...

How can I trigger a method upon leaving a page in C# (.Net 3.5)?

I am currently developing a project where users are granted a certain level of "authentication" when they land on a specific page, and I need a way to revoke this "authentication" if they attempt to leave the page before completing a form. Is there a meth ...

Automating the WebDriver script in JMeter with advanced tools

Are there any tools available that can assist in creating automation scripts for WebDriver within JMeter? ...

What is the best way to monitor and record the height of a div element in a React application?

Exploring the Height of a Div I am interested in monitoring the height of a div element so that I can dynamically adjust distances based on varying screen widths. The animation should respond to changes in screen width, such as when text stacks and the he ...

Unit testing setTimeout in a process.on callback using Jest in NodeJS

I've been struggling with unit testing a timer using Jest within my process.on('SIGTERM') callback, but it doesn't seem to be triggered. I have implemented jest.useFakeTimers() and while it does mock the setTimeout call to some extent, ...

Selecting specific elements from an array in JavaScript can be achieved by using various methods and techniques

Currently working on a quiz incentive system where users earn rewards based on the number of correct answers they input. The example array below shows the possible range of correct answers: var rightAnswers = ['a', 'b', 'c' ...

Abbreviating Column Labels in Google Visualization

Is there a way to use the google visualization API to display column headers in an abbreviated form in a table, but show the full labels in a pie chart using the same dataset? Check out this snippet of JavaScript: //create the dashboard and table chart ...

Using Vue to handle Promise resolution - incorporating Laravel Gate logic into Vue

Trying to incorporate Laravel's authorization and policy into Vue has been a challenge for me. I'm working on creating a mixin that sends a GET request to a backend controller. The issue I've encountered is that the v-if directive is receiv ...

What are some effective strategies for resolving the persistent issue of Visual Studio Code warnings, MDN Reference difficulties, and other challenges?

Is there a way to turn off TypeScript warnings and completely disable TS in Visual Studio Code for standard JavaScript files while using SvelteKit? I typically opt out of using TS when starting a new project. Furthermore, is it possible to get rid of the ...

Trouble with selecting inputs within a Div Element

Could you please review the code below and help me understand why I am unable to retrieve the ID of the selected radio buttons using this.id? <div id="pay" class="btn-group" data-toggle="buttons"> <label class="btn btn-primary"> < ...

Use two separate AJAX requests to open and close the modal dialog

I am experiencing an issue with my subscription form that uses modal windows. After closing the window and trying to subscribe again, the ajax calls are being duplicated, resulting in an error. $("#openModal").click(function() { if($("#wname").val() = ...

Discovering distinct colors for this loading dots script

Looking for assistance with a 10 loading dots animation script. I'm trying to customize the color of each dot individually, but when I create separate divs for each dot and control their colors in CSS, it causes issues with the animation. If anyone ...

Guide to using Razor syntax in JQuery to effortlessly redirect to a different page

$(".category-sub-opition-list li").click(function () { var id = $(this).attr("id"); var category = getUrlParameter('category'); @{ var category = Request.QueryString["category"]; var cat = Model.Ite ...

Managing localization in MongoDB

Looking to manage localization data in MongoDB, what is the best approach for handling locale? To better understand, consider a sample document: `{ "_id" : ObjectId("595a05f2a5ace827b4434d94"), "name" : "Broadway Center", "url" : "bc.example. ...

Using Selenium Webdriver to choose a value from a Dropdown menu may require more time than expected

I recently encountered an issue with inspecting a value from a dropdown. The dropdown I was working with was not within a select class, but rather nested under ul->li. This dropdown had a list of values under <li>. I attempted to retrieve all the ...

Restricting the time frame in HTML 5

My form includes an input field with the type date <input type="date" id="datepick" name="mybirthday" placeholder="Birthdate(MM/DD/YYYY)" /> I am looking to restrict the date range that users can select. I specifically do not want users to be able ...

Using *ngIf can lead to a never-ending cycle that never gets resolved

I am currently working on a project using Angular and I need to conditionally display a form based on certain values. I have successfully tested the backend route using Postman and everything is functioning correctly. Here is a snippet of my code: Block ...