1

Same question was asked for python here: Selenium - wait until element is present, visible and interactable. However the answers are not covering all the scenarios.

My implementation fails from time to time, when I am not in debug mode. I consider that waiting for an ID is such a trivial task that should have a straight forward KISS implementation and should never fail.

    public IWebElement WaitForId(string inputId, bool waitToInteract = false, int index = 0)
    {
        IWebElement uiElement = null;
        while (uiElement == null)
        {
            var items = WebDriver.FindElements(By.Id(inputId));
            var iteration = 0;
            while (items == null || items.Count < (index + 1) ||
                   (waitToInteract && (!items[index].Enabled || !items[index].Displayed)))
            {
                Thread.Sleep(500);
                items = WebDriver.FindElements(By.Id(inputId));
                if (items.Count == 0 && iteration == 10)
                {
                    // "still waiting...: " + inputId
                }

                if (iteration == 50)
                {
                    // "WaitForId not found: " + inputId
                    Debugger.Break(); // if tried too many times, maybe you want to investigate way
                }

                iteration++;
            }
            uiElement = WebDriver.FindElement(By.Id(inputId));
        }
        return uiElement;
    }
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
profimedica
  • 2,716
  • 31
  • 41
  • " I consider that waiting for an ID is such a trivial task..." - nothing is ever easy. Can you [edit] your question to describe how you are interacting with this scrollable modal? – Greg Burghardt Apr 09 '21 at 14:48

1 Answers1

0
    public IWebElement GetActiveElement(string id, int allowedTimeout = 20, int retryInterval = 250)
    {
      var wait = new DefaultWait<IWebDriver>(_driver)
      {
        Timeout = TimeSpan.FromSeconds(allowedTimeout),
        PollingInterval = TimeSpan.FromMilliseconds(retryInterval)
      };

      return wait.Until(d =>
      {
        var element = d.FindElement(By.Id(id));
        return element.Displayed || element.Enabled ? element : throw new NoSuchElementException();
      });

   // Usage would be something like this

GetActiveElement("foo").SendKeys("Bar");

You should be able to create extension method and call the extension instead

public static class WebDriverExtension
  {
    public static IWebElement GetActiveElement(this IWebDriver driver, string id, int allowedTimeout = 20, int retryInterval = 250)
    {
      var wait = new DefaultWait<IWebDriver>(driver)
      {
        Timeout = TimeSpan.FromSeconds(allowedTimeout),
        PollingInterval = TimeSpan.FromMilliseconds(retryInterval)
      };

      return wait.Until(d =>
      {
        var element = d.FindElement(By.Id(id));
        return element.Displayed || element.Enabled ? element : throw new NoSuchElementException();
      });
    }
  }

// usage 
_driver.GetActiveElement("foo").SendKeys("bar");