Alessio Raddi
Alessio Raddi

Reputation: 622

Selenium C# ElementNotVisibleException: element not interactable but the element is actually visible

I'm using Selenium.WebDriver for C# to ask a question on Quora just typing my question in notepad.

Everything worked fine since I had to post it.

To post it I need to click on a link inside a span like this:

<span id="__w2_wEA6apRq1_submit_question">
  <a class="submit_button modal_action" href="#" id="__w2_wEA6apRq1_submit">Add Question</a>
</span>

In order to click it I've tried this method, that I've used for all my previous button clicks:

Selecting the element and clicking it:

var element = driver.FindElement(By.CssSelector(".submit_button.modal_action"));
element.Click();

Doing so I can get the element, but unfortunately it throws "ElementNotVisibleException". Debugging my application I could see that Displayed property was set to False, while it wasn't, because in my ChromeDriver I could clearly see the button.

To avoid clicking the element, I tried IJavaScriptExecutor and Driver.ExecuteJavaScript(); to click the link through a script:

IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
js.ExecuteScript("arguments[0].click()", element);

Same logic has been used for Driver.ExecuteJavaScript(); but I get the same result, but when I write the same script into DevTools's Console tab it works perfectly.

How can I solve this issue?

Upvotes: 3

Views: 8978

Answers (2)

undetected Selenium
undetected Selenium

Reputation: 193108

As per the HTML you have shared to click on the element with text as Add Question as the element is within a Modal Dialog you need to induce WebDriverWait for the desired ElementToBeClickable and you can use either of the following Locator Strategies as solutions:

  • LinkText:

    new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.LinkText("Add Question"))).Click();
    
  • CssSelector:

    new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.CssSelector("span[id$='_submit_question']>a.submit_button.modal_action"))).Click();
    
  • XPath:

    new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//span[contains(@id,'_submit_question')]/a[@class='submit_button modal_action' and contains(.,'Add Question')]"))).Click();
    

Upvotes: 2

Angel Dinev
Angel Dinev

Reputation: 489

You might have a case where the button become displayed(visible) after your check is executed, so you might try following delay in order to ensure that the button is displayed at the time of check:

public static void WaitForElementToBecomeVisibleWithinTimeout(IWebDriver driver, 
    IWebElement element, int timeout)
{
    new WebDriverWait(driver,                 
        TimeSpan.FromSeconds(timeout)).Until(ElementIsVisible(element));
}

private static Func<IWebDriver, bool> ElementIsVisible(IWebElement element)
{
    return driver =>
    {
        try
        {
            return element.Displayed;
        }
        catch (Exception)
        {
            // If element is null, stale or if it cannot be located
            return false;
        }
    };
}

If the button is not visible in the viewport(i.e. need scrolling to become visible) then you may scroll it with

public static void ScrollElementToBecomeVisible(IWebDriver driver, IWebElement element)
{
    IJavaScriptExecutor jsExec = (IJavaScriptExecutor)driver;
    jsExec.ExecuteScript("arguments[0].scrollIntoView(true);", element);
}

Upvotes: 1

Related Questions