private void HandleTimeoutException(WebDriverTimeoutException ex, ElementStates elementState, By selector, List <IWebElement> foundElements)
        {
            var message = $"No elements with selector '{selector}' were found in {elementState.StateName} elementState";

            if (elementState.IsCatchingTimeoutException)
            {
                if (!foundElements.Any())
                {
                    if (elementState.IsThrowingNoSuchElementException)
                    {
                        throw new NoSuchElementException(message);
                    }
                    Logger.Instance.Debug($"No elements with selector '{selector}' were found in {elementState.StateName} elementState");
                }
                else
                {
                    Logger.Instance.Debug($"Elements were found by selector '{selector}' but not in elementState {elementState.StateName}");
                }
            }
            else
            {
                var combinedMessage = $"{ex.Message}: {message}";
                if (elementState.IsThrowingNoSuchElementException && !foundElements.Any())
                {
                    throw new NoSuchElementException(combinedMessage);
                }
                throw new WebDriverTimeoutException(combinedMessage);
            }
        }
        public IWebElement FindElement(By selector, Func <IWebElement, bool> elementStateCondition, string stateName, TimeSpan?timeout = null)
        {
            var desiredState = new ElementStates(elementStateCondition, stateName)
            {
                IsCatchingTimeoutException       = false,
                IsThrowingNoSuchElementException = true
            };

            return(FindElements(selector, desiredState, timeout).First());
        }
        public ReadOnlyCollection <IWebElement> FindElements(By selector, ElementStates elementState, TimeSpan?timeout = null)
        {
            var foundElements  = new List <IWebElement>();
            var resultElements = new List <IWebElement>();

            try
            {
                SmartWait.WaitFor(driver =>
                {
                    foundElements  = driver.FindElements(selector).ToList();
                    resultElements = foundElements.Where(elementState.ElementStateCondition).ToList();
                    return(resultElements.Any());
                }, timeout);
            }
            catch (WebDriverTimeoutException ex)
            {
                HandleTimeoutException(ex, elementState, selector, foundElements);
            }
            return(resultElements.AsReadOnly());
        }