public static string[] GetElementsTextWhenVisible(this IWebDriver driver, By locator)
        {
            string[] WebDriverActions()
            {
                driver.Wait().Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(locator));
                return(driver.FindElements(locator).Select(e => e.Text.Trim()).ToArray());
            }

            return(FunctionRetrier.RetryOnException <string[], StaleElementReferenceException>(WebDriverActions));
        }
        public static void ClickLastElementWhenVisible(this IWebDriver driver, By locator)
        {
            void WebDriverActions()
            {
                driver.Wait().Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(locator));
                ReadOnlyCollection <IWebElement> elements = driver.FindElements(locator);

                elements.Last().Click();
            }

            FunctionRetrier.RetryOnException <StaleElementReferenceException>(WebDriverActions);
        }
        public static void SetTextBoxValueWhenVisible(this IWebDriver driver, By locator, string value)
        {
            void WebDriverActions()
            {
                IWebElement element = driver.Wait().Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(locator));

                element.Clear();
                element.SendKeys(value);
            }

            FunctionRetrier.RetryOnException <StaleElementReferenceException>(WebDriverActions);
        }
        public static void ClickElementWhenExists(this IWebDriver driver, By locator)
        {
            void WebDriverActions()
            {
                IWebElement elementToClick = driver.Wait().Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(locator));

                new Actions(driver)
                .MoveToElement(elementToClick)
                .Click()
                .Perform();
            }

            FunctionRetrier.RetryOnException <StaleElementReferenceException>(WebDriverActions);
        }
        public static void SendKeysWhenVisible(this IWebDriver driver, By locator, string keys)
        {
            void WebDriverActions()
            {
                IWebElement element = driver.Wait().Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(locator));

                new Actions(driver)
                .MoveToElement(element)
                .Click()
                .SendKeys(keys)
                .Perform();
            }

            FunctionRetrier.RetryOnException <StaleElementReferenceException>(WebDriverActions);
        }
        public static void WaitForSpinners(this IWebDriver driver, By locator)
        {
            bool AreAllSpinnersInvisible()
            {
                ReadOnlyCollection <IWebElement> spinnerElements = driver.FindElements(locator);

                return(spinnerElements.None(e => e.Displayed));
            }

            bool allSpinnersAreInvisible = Poller.PollForSuccess(() => FunctionRetrier.RetryOnException <bool, StaleElementReferenceException>(AreAllSpinnersInvisible));

            if (!allSpinnersAreInvisible)
            {
                throw new Exception("Spinners are still present after waiting");
            }
        }
        public static int GetDisplayedElementCount(this IWebDriver driver, By locator)
        {
            int WebDriverActions()
            {
                try
                {
                    return(driver.FindElements(locator).Count(e => e.Displayed));
                }
                catch (NoSuchElementException)
                {
                    return(0);
                }
            }

            return(FunctionRetrier.RetryOnException <int, StaleElementReferenceException>(WebDriverActions));
        }
        public static string[] GetElementsTextIfExists(this IWebDriver driver, By locator)
        {
            string[] WebDriverActions()
            {
                driver.Wait(1).Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(locator));
                return(driver.FindElements(locator).Select(e => e.Text.Trim()).ToArray());
            }

            try
            {
                return(FunctionRetrier.RetryOnException <string[], StaleElementReferenceException>(WebDriverActions, 1));
            }
            catch (WebDriverTimeoutException wde) when(wde.InnerException is NoSuchElementException)
            {
                return(Array.Empty <string>());
            }
        }
        public static void DragAndDropElement(this IWebDriver driver, By elementToDragLocator, By elementToDropOntoLocator)
        {
            void WebDriverActions()
            {
                IWebElement elementToDrag     = driver.Wait().Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(elementToDragLocator));
                IWebElement elementToDropOnto = driver.Wait().Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(elementToDropOntoLocator));

                new Actions(driver)
                .ClickAndHold(elementToDrag)
                .MoveToElement(elementToDropOnto)
                .Release(elementToDrag)
                .Build()
                .Perform();
            }

            FunctionRetrier.RetryOnException <StaleElementReferenceException>(WebDriverActions);
        }
        public static void ClickElementAtOffsetWhenClickable(this IWebDriver driver, By locator, int x, int y)
        {
            void WebDriverActions()
            {
                IWebElement elementToClick = driver.Wait().Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(locator));

                Size size = elementToClick.Size;

                new Actions(driver)
                .MoveToElement(elementToClick)
                .MoveByOffset(size.Width / 2, size.Height / 2)
                .MoveByOffset(x, y)
                .Click()
                .Perform();
            }

            FunctionRetrier.RetryOnException <StaleElementReferenceException>(WebDriverActions);
        }
        public static IList <IWebElement> GetElementsWhenVisible(this IWebDriver driver, By locator)
        {
            IWebElement[] foundVisibleElements = Array.Empty <IWebElement>();

            IWebElement[] WebDriverActions() => driver.FindElements(locator).Where(e => e.Displayed).ToArray();

            Poller.PollForSuccess(() =>
            {
                foundVisibleElements = FunctionRetrier.RetryOnException <IWebElement[], StaleElementReferenceException>(WebDriverActions);
                return(foundVisibleElements.Any());
            });

            if (foundVisibleElements.None())
            {
                throw new Exception($"No visible elements found for locator {locator}");
            }

            return(foundVisibleElements);
        }
        public static bool IsElementSelected(this IWebDriver driver, By locator)
        {
            bool WebDriverActions() => driver.Wait().Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(locator)).Selected;

            return(FunctionRetrier.RetryOnException <bool, StaleElementReferenceException>(WebDriverActions));
        }
        public static string GetElementTextWhenVisible(this IWebDriver driver, By locator)
        {
            string WebDriverActions() => driver.Wait().Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(locator)).Text;

            return(FunctionRetrier.RetryOnException <string, StaleElementReferenceException>(WebDriverActions));
        }