<commit_before>using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using OpenQA.Selenium;
using OpenQA.Selenium.Interactions;
using OpenQA.Selenium.Internal;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Support.UI;
using Signum.Utilities;

namespace Signum.React.Selenium
{
    public static class SeleniumExtensions
    {
        public static TimeSpan DefaultTimeout = TimeSpan.FromMilliseconds(20 * 1000);
        public static TimeSpan ThrowExceptionForDeveloperAfter = TimeSpan.FromMilliseconds(5 * 1000);
        public static TimeSpan DefaultPoolingInterval = TimeSpan.FromMilliseconds(200);

        public static T Wait<T>(this RemoteWebDriver selenium, Func<T> condition, Func<string>? actionDescription = null, TimeSpan? timeout = null)
        {
            try
            {
                var wait = new DefaultWait<string>("")
                {
                    Timeout = timeout ?? DefaultTimeout,
                    PollingInterval = DefaultPoolingInterval
                };

                wait.IgnoreExceptionTypes(typeof(NoSuchElementException), typeof(NoAlertPresentException), typeof(StaleElementReferenceException));
                var throwExceptionAfter = Debugger.IsAttached ? DateTime.Now.Add(ThrowExceptionForDeveloperAfter) : (DateTime?)null;
                return wait.Until(str =>
                {
                    var result = condition();

                    if ((result == null || result.Equals(false)) && throwExceptionAfter < DateTime.Now)
                    {
                        try
                        {
                            throw new WaitTakingTooLongException("Hey Developer! looks like this condition is taking too long");
                        }
                        catch (WaitTakingTooLongException)
                        {
                            throwExceptionAfter = null;
                            return result;
                        }
                    }

                    return result;
                });
            }
            catch (WebDriverTimeoutException ex)
            {
                throw new WebDriverTimeoutException(ex.Message + ": waiting for {0} in page {1}({2})".FormatWith(
                    actionDescription == null ? "visual condition" : actionDescription(),
                    selenium.Title,
                    selenium.Url));
            }
        }


        [Serializable]
        public class WaitTakingTooLongException : Exception
        {
            public WaitTakingTooLongException() { }
            public WaitTakingTooLongException(string message) : base(message) { }
            public WaitTakingTooLongException(string message, Exception inner) : base(message, inner) { }
            protected WaitTakingTooLongException(
              System.Runtime.Serialization.SerializationInfo info,
              System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
        }

        public static string WaitNewWindow(this RemoteWebDriver selenium, Action action)
        {
            var old = selenium.WindowHandles.ToHashSet();
            action();
            return selenium.Wait(() => selenium.WindowHandles.SingleOrDefaultEx(a => !old.Contains(a)))!;
        }

        public static void WaitEquals<T>(this RemoteWebDriver selenium, T expectedValue, Func<T> value, TimeSpan? timeout = null)
        {
            T lastValue = default(T)!;
            selenium.Wait(() => EqualityComparer<T>.Default.Equals(lastValue = value(), expectedValue), () => "expression to be " + expectedValue + " but is " + lastValue, timeout);
        }

        public static IWebElement TryFindElement(this RemoteWebDriver selenium, By locator)
        {
            return selenium.FindElements(locator).FirstOrDefault();
        }

        public static IWebElement TryFindElement(this IWebElement element, By locator)
        {
            return element.FindElements(locator).FirstOrDefault();
        }

        public static IWebElement WaitElementPresent(this RemoteWebDriver selenium, By locator, Func<string>? actionDescription = null, TimeSpan? timeout = null)
        {
            return selenium.Wait(() => selenium.FindElements(locator).FirstOrDefault(),
                actionDescription ?? (Func<string>)(() => "{0} to be present".FormatWith(locator)), timeout);
        }

        public static IWebElement WaitElementPresent(this IWebElement element, By locator, Func<string>? actionDescription = null, TimeSpan? timeout = null)
        {
            return element.GetDriver().Wait(() => element.FindElements(locator).FirstOrDefault(),
                actionDescription ?? (Func<string>)(() => "{0} to be present".FormatWith(locator)), timeout);
        }

        public static void AssertElementPresent(this RemoteWebDriver selenium, By locator)
        {
            if (!selenium.IsElementPresent(locator))
                throw new InvalidOperationException("{0} not found".FormatWith(locator));
        }

        public static void AssertElementPresent(this IWebElement element, By locator)
        {
            if (!element.IsElementPresent(locator))
                throw new InvalidOperationException("{0} not found".FormatWith(locator));
        }

        public static bool IsElementPresent(this RemoteWebDriver selenium, By locator)
        {
            return selenium.FindElements(locator).Any();
        }

        public static bool IsElementPresent(this IWebElement element, By locator)
        {
            return element.FindElements(locator).Any();
        }

        public static void WaitElementNotPresent(this RemoteWebDriver selenium, By locator, Func<string>? actionDescription = null, TimeSpan? timeout = null)
        {
            selenium.Wait(() => !selenium.IsElementPresent(locator),
                actionDescription ?? (Func<string>)(() => "{0} to be not present".FormatWith(locator)), timeout);
        }

        public static void WaitElementNotPresent(this IWebElement element, By locator, Func<string>? actionDescription = null, TimeSpan? timeout = null)
        {
            element.GetDriver().Wait(() => !element.IsElementPresent(locator),
                actionDescription ?? (Func<string>)(() => "{0} to be not present".FormatWith(locator)), timeout);
        }

        public static void AssertElementNotPresent(this RemoteWebDriver selenium, By locator)
        {
            if (selenium.IsElementPresent(locator))
                throw new InvalidOperationException("{0} is found".FormatWith(locator));
        }

        public static void AssertElementNotPresent(this IWebElement element, By locator)
        {
            if (element.IsElementPresent(locator))
                throw new InvalidOperationException("{0} is found".FormatWith(locator));
        }

        //[DebuggerHidden]
        public static bool IsStale(this IWebElement element)
        {
            //try
            //{
            //    // Calling any method forces a staleness check
            //    return element == null || !element.Enabled;
            //}
            //catch (StaleElementReferenceException)
            //{
            //    return true;
            //}
            return SeleniumExtras.WaitHelpers.ExpectedConditions.StalenessOf(element)(element.GetDriver());
        }

        public static IWebElement WaitElementVisible(this RemoteWebDriver selenium, By locator, Func<string>? actionDescription = null, TimeSpan? timeout = null)
        {
            return selenium.Wait(() => selenium.FindElements(locator).FirstOrDefault(a => a.Displayed),
                actionDescription ?? (Func<string>)(() => "{0} to be visible".FormatWith(locator)), timeout);
        }

        public static IWebElement WaitElementVisible(this IWebElement element, By locator, Func<string>? actionDescription = null, TimeSpan? timeout = null)
        {
            return element.GetDriver().Wait(() => element.FindElements(locator).FirstOrDefault(a => a.Displayed),
                actionDescription ?? (Func<string>)(() => "{0} to be visible".FormatWith(locator)), timeout);
        }

        public static void AssertElementVisible(this RemoteWebDriver selenium, By locator)
        {
            var elements = selenium.FindElements(locator);

            if (!elements.Any())
                throw new InvalidOperationException("{0} not found".FormatWith(locator));

            if (!elements.First().Displayed)
                throw new InvalidOperationException("{0} found but not visible".FormatWith(locator));
        }

        public static bool IsElementVisible(this RemoteWebDriver selenium, By locator)
        {
            var elements = selenium.FindElements(locator);
            try
            {
                return elements.Any() && elements.First().Displayed;
            }
            catch (StaleElementReferenceException)
            {
                return false;
            }
        }

        public static bool IsElementVisible(this IWebElement element, By locator)
        {<commit_msg>add WaitElementsVisible<commit_after>using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using OpenQA.Selenium;
using OpenQA.Selenium.Interactions;
using OpenQA.Selenium.Internal;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Support.UI;
using Signum.Utilities;

namespace Signum.React.Selenium
{
    public static class SeleniumExtensions
    {
        public static TimeSpan DefaultTimeout = TimeSpan.FromMilliseconds(20 * 1000);
        public static TimeSpan ThrowExceptionForDeveloperAfter = TimeSpan.FromMilliseconds(5 * 1000);
        public static TimeSpan DefaultPoolingInterval = TimeSpan.FromMilliseconds(200);

        public static T Wait<T>(this RemoteWebDriver selenium, Func<T> condition, Func<string>? actionDescription = null, TimeSpan? timeout = null)
        {
            try
            {
                var wait = new DefaultWait<string>("")
                {
                    Timeout = timeout ?? DefaultTimeout,
                    PollingInterval = DefaultPoolingInterval
                };

                wait.IgnoreExceptionTypes(typeof(NoSuchElementException), typeof(NoAlertPresentException), typeof(StaleElementReferenceException));
                var throwExceptionAfter = Debugger.IsAttached ? DateTime.Now.Add(ThrowExceptionForDeveloperAfter) : (DateTime?)null;
                return wait.Until(str =>
                {
                    var result = condition();

                    if ((result == null || result.Equals(false)) && throwExceptionAfter < DateTime.Now)
                    {
                        try
                        {
                            throw new WaitTakingTooLongException("Hey Developer! looks like this condition is taking too long");
                        }
                        catch (WaitTakingTooLongException)
                        {
                            throwExceptionAfter = null;
                            return result;
                        }
                    }

                    return result;
                });
            }
            catch (WebDriverTimeoutException ex)
            {
                throw new WebDriverTimeoutException(ex.Message + ": waiting for {0} in page {1}({2})".FormatWith(
                    actionDescription == null ? "visual condition" : actionDescription(),
                    selenium.Title,
                    selenium.Url));
            }
        }


        [Serializable]
        public class WaitTakingTooLongException : Exception
        {
            public WaitTakingTooLongException() { }
            public WaitTakingTooLongException(string message) : base(message) { }
            public WaitTakingTooLongException(string message, Exception inner) : base(message, inner) { }
            protected WaitTakingTooLongException(
              System.Runtime.Serialization.SerializationInfo info,
              System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
        }

        public static string WaitNewWindow(this RemoteWebDriver selenium, Action action)
        {
            var old = selenium.WindowHandles.ToHashSet();
            action();
            return selenium.Wait(() => selenium.WindowHandles.SingleOrDefaultEx(a => !old.Contains(a)))!;
        }

        public static void WaitEquals<T>(this RemoteWebDriver selenium, T expectedValue, Func<T> value, TimeSpan? timeout = null)
        {
            T lastValue = default(T)!;
            selenium.Wait(() => EqualityComparer<T>.Default.Equals(lastValue = value(), expectedValue), () => "expression to be " + expectedValue + " but is " + lastValue, timeout);
        }

        public static IWebElement TryFindElement(this RemoteWebDriver selenium, By locator)
        {
            return selenium.FindElements(locator).FirstOrDefault();
        }

        public static IWebElement TryFindElement(this IWebElement element, By locator)
        {
            return element.FindElements(locator).FirstOrDefault();
        }

        public static IWebElement WaitElementPresent(this RemoteWebDriver selenium, By locator, Func<string>? actionDescription = null, TimeSpan? timeout = null)
        {
            return selenium.Wait(() => selenium.FindElements(locator).FirstOrDefault(),
                actionDescription ?? (Func<string>)(() => "{0} to be present".FormatWith(locator)), timeout);
        }

        public static IWebElement WaitElementPresent(this IWebElement element, By locator, Func<string>? actionDescription = null, TimeSpan? timeout = null)
        {
            return element.GetDriver().Wait(() => element.FindElements(locator).FirstOrDefault(),
                actionDescription ?? (Func<string>)(() => "{0} to be present".FormatWith(locator)), timeout);
        }

        public static void AssertElementPresent(this RemoteWebDriver selenium, By locator)
        {
            if (!selenium.IsElementPresent(locator))
                throw new InvalidOperationException("{0} not found".FormatWith(locator));
        }

        public static void AssertElementPresent(this IWebElement element, By locator)
        {
            if (!element.IsElementPresent(locator))
                throw new InvalidOperationException("{0} not found".FormatWith(locator));
        }

        public static bool IsElementPresent(this RemoteWebDriver selenium, By locator)
        {
            return selenium.FindElements(locator).Any();
        }

        public static bool IsElementPresent(this IWebElement element, By locator)
        {
            return element.FindElements(locator).Any();
        }

        public static void WaitElementNotPresent(this RemoteWebDriver selenium, By locator, Func<string>? actionDescription = null, TimeSpan? timeout = null)
        {
            selenium.Wait(() => !selenium.IsElementPresent(locator),
                actionDescription ?? (Func<string>)(() => "{0} to be not present".FormatWith(locator)), timeout);
        }

        public static void WaitElementNotPresent(this IWebElement element, By locator, Func<string>? actionDescription = null, TimeSpan? timeout = null)
        {
            element.GetDriver().Wait(() => !element.IsElementPresent(locator),
                actionDescription ?? (Func<string>)(() => "{0} to be not present".FormatWith(locator)), timeout);
        }

        public static void AssertElementNotPresent(this RemoteWebDriver selenium, By locator)
        {
            if (selenium.IsElementPresent(locator))
                throw new InvalidOperationException("{0} is found".FormatWith(locator));
        }

        public static void AssertElementNotPresent(this IWebElement element, By locator)
        {
            if (element.IsElementPresent(locator))
                throw new InvalidOperationException("{0} is found".FormatWith(locator));
        }

        //[DebuggerHidden]
        public static bool IsStale(this IWebElement element)
        {
            //try
            //{
            //    // Calling any method forces a staleness check
            //    return element == null || !element.Enabled;
            //}
            //catch (StaleElementReferenceException)
            //{
            //    return true;
            //}
            return SeleniumExtras.WaitHelpers.ExpectedConditions.StalenessOf(element)(element.GetDriver());
        }

        public static IWebElement WaitElementVisible(this RemoteWebDriver selenium, By locator, Func<string>? actionDescription = null, TimeSpan? timeout = null)
        {
            return selenium.Wait(() => selenium.FindElements(locator).FirstOrDefault(a => a.Displayed),
                actionDescription ?? (Func<string>)(() => "{0} to be visible".FormatWith(locator)), timeout);
        }

        public static IWebElement WaitElementVisible(this IWebElement element, By locator, Func<string>? actionDescription = null, TimeSpan? timeout = null)
        {
            return element.GetDriver().Wait(() => element.FindElements(locator).FirstOrDefault(a => a.Displayed),
                actionDescription ?? (Func<string>)(() => "{0} to be visible".FormatWith(locator)), timeout);
        }

        public static ReadOnlyCollection<IWebElement> WaitElementsVisible(this RemoteWebDriver selenium, By locator, TimeSpan? timeout = null)
        {
            return new WebDriverWait(selenium, timeout ?? DefaultTimeout)
                .Until(SeleniumExtras.WaitHelpers.ExpectedConditions.VisibilityOfAllElementsLocatedBy(locator));
        }

        public static ReadOnlyCollection<IWebElement> WaitElementsVisible(this IWebElement element, By locator, TimeSpan? timeout = null)
        {
            return new WebDriverWait(element.GetDriver(), timeout ?? DefaultTimeout)
                .Until(SeleniumExtras.WaitHelpers.ExpectedConditions.VisibilityOfAllElementsLocatedBy(locator));
        }

        public static void AssertElementVisible(this RemoteWebDriver selenium, By locator)
        {
            var elements = selenium.FindElements(locator);

            if (!elements.Any())
                throw new InvalidOperationException("{0} not found".FormatWith(locator));

            if (!elements.First().Displayed)
                throw new InvalidOperationException("{0} found but not visible".FormatWith(locator));
        }

        public static bool IsElementVisible(this RemoteWebDriver selenium, By locator)
        {
            var elements = selenium.FindElements(locator);
            try
            {
                return elements.Any() && elements.First().Displayed;
            }
            catch (StaleElementReferenceException)
            {
                return false;
            }
        }

        public static bool IsElementVisible(this IWebElement element, By locator)
        {
{'fraction_non_alphanumeric': 0.09418457648546144, 'fraction_numerical': 0.003055204382638011, 'mean_word_length': 2.262588073552157, 'pattern_counts': {'":': 2, '<': 45, '<?xml version=': 0, '>': 81, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2491399', 'n_tokens_mistral': 4736, 'n_tokens_neox': 4456, 'n_words': 1083}