Search code examples
c#.netselenium-webdriverui-automation

How to Get WebElement Uninue Identifier on html Page (Selenium, C#)


I want to create Child of WebElement class (.Net) but the thing is WebElement contsructor takes 2 argumnets (driver, id) I know how to get id of an element if it has visible attribute ID, but if it has not What is the way to get it

    public class CoreWebelement : WebElement
    {
        IWebDriver driver;
        public CoreWebelement(WebDriver parentDriver, string id, By? parentFrame = null) : base(parentDriver, id)
        {
            driver = parentDriver;
        }
        public void ClickJS()
        {
            IJavaScriptExecutor jsExecutor = (IJavaScriptExecutor)driver;
            jsExecutor.ExecuteScript("arguments[0].click();", this);         
        }
    }

I tried to find it insided WebElement class but it is protected, so I can not get from outside Also Tried basic thing like element.GetAttribute("ID") and js: element.id , but as I said it only works if element has visible ID Attribute


Solution

  • The id in the WebElement constructor is not a By.Id() (locator type) like you are thinking... it's a string id which is more of a GUID that uniquely identifies that particular WebElement amongst all of the elements on the page. You can see this in the XML docs for that constructor,

    /// <summary>
    /// Initializes a new instance of the <see cref="WebElement"/> class.
    /// </summary>
    /// <param name="parentDriver">The <see cref="WebDriver"/> instance that is driving this element.</param>
    /// <param name="id">The ID value provided to identify the element.</param>
    public WebElement(WebDriver parentDriver, string id)
    

    and the XML docs for the Id property of WebElement,

    /// <summary>
    /// Gets the ID of the element
    /// </summary>
    /// <remarks>This property is internal to the WebDriver instance, and is
    /// not intended to be used in your code. The element's ID has no meaning
    /// outside of internal WebDriver usage, so it would be improper to scope
    /// it as public...
    

    One way to do this is to create an extension method for WebElement (NOTE: *not* IWebElement). This will allow you to get the element.ClickJs() syntax you are looking for. The downside to this approach is that you need to access Driver but you can't get it using IWebElement that Driver.FindElement() returns. WebElement inherits from IWebElement so you can cast the return to a WebElement and use element.WrappedDriver to get access to the Driver instance.

    You create the extension method using the code below,

    public static class WebElementExtensions
    {
        public static void ClickJs(this WebElement element)
        {
            ((IJavaScriptExecutor)element.WrappedDriver).ExecuteScript("arguments[0].click();", element);
        }
    }
    

    then you call it like

    var e = (WebElement)driver.FindElement(...);
    e.ClickJs();
    

    or a one-liner

    ((WebElement)driver.FindElement(...)).ClickJs();