t.me/atinfo_chat Telegram группа по автоматизации тестирования

Проблема с ожиданием исчезновения спиннера C#

csharp
wait
webdriver
selenium
Теги: #<Tag:0x00007f9c5cead7b0> #<Tag:0x00007f9c5cead670> #<Tag:0x00007f9c5cead4b8> #<Tag:0x00007f9c5cead378>

(Lelik) #1
В ходе разработки в приложении появился "спиннер" и как результат задача подождать пока он исчезнет, что бы нажать на нужный элемент.

В коде он выглядит так:

image

Элемент я нашла.
[FindsBy(How = How.XPath, Using = “//mat-progress-spinner//descendant-or-self::*[3]”)]
Реализация ожидания ниже.


        internal static void WaitForLoading()
        {
            var commonElements = new CommonElements();

            while (string.IsNullOrWhiteSpace(commonElements.divLoader.GetAttribute("circle")))
                PropertiesCollection.Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(15);
            ;
        }

Но увы:

Message: System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
----> OpenQA.Selenium.StaleElementReferenceException : stale element reference: element is not attached to the page document

Подскажите плиз, что я делаю не так


(Vladislav Abramov) #2

найдите все элементы класса спиннер и дождитесь исчезновения каждого из них


(Vladislav Abramov) #3

что то типа

var Spinners = Browser.FindElements(By.Xpath("//*[@class = 'spinner']"));

Spinners.ForEach(s => Browser.WaitElementHide(s));

(Lelik) #4

Дело в том что элемент как таковой не исчезает, а просто становится c атрибутом hidden


(Alexandr D.) #5

Ищет все спиннеры и ждёт пока все, которые появились - исчезнут.

Ключевое здесь то, что надо всегда заново искать элементы, чтобы избежать StaleElementReferenceException.

public static void WaitLoader(TimeSpan timeToWaitLoader = default, TimeSpan timeToWaitDissapearLoader = default)
{
    const string loaderName = "Крутилка (лоадер)";
    if (timeToWaitLoader == default) timeToWaitLoader = TimeSpan.FromMilliseconds(1600);
    if (timeToWaitDissapearLoader == default) timeToWaitDissapearLoader = TimeSpan.FromSeconds(15);
    var bys = By.XPath("//*[contains(@class, \'spinner\')]");
    var stepResult = false;
    AllureLifecycle.Instance.RunStep($"Ожидание => {loaderName} может появиться за {timeToWaitLoader}",
        () =>
        {
            stepResult = DriverManager.Driver.Wait(timeToWaitLoader).Until(_ =>
            {
                var list = _.FindElements(bys);
                return list.Any(w => w.Exists());
            });
        });

    if (stepResult)
        AllureLifecycle.Instance.RunStep(
            $"Ожидание => {loaderName} должна исчезнуть за {timeToWaitDissapearLoader}.",
            () =>
            {
                var result = DriverManager.Driver.Wait(timeToWaitDissapearLoader).Until(_ =>
                {
                    var list = _.FindElements(bys);
                    return list.All(w => w.NotExists());
                });
                if (!result)
                {
                    AllureLifecycle.Instance.Verify.Warn(
                        $"{loaderName} не исчезла за {timeToWaitDissapearLoader}.");
                    var strategy = new VerticalCombineDecorator(new ScreenshotMaker());
                    DriverManager.MakeScreenshotAtCurrentStep(strategy);
                }
            });
    else AllureLifecycle.Instance.Verify.Pass($"{loaderName} не появилась");
}

Метод Exists - возвращает тру, если элемент существует в ДОМ и имеет Displayed = true.
NotExists - инверт Exists


(Vladislav Abramov) #6

можно как в селениде написать метод, который рекурсивно проверять наличие класса hidden у элемента, на который вы стрелкой указали, в течение какого времени


(Сергей Слётов) #7

А в Selenium C# отсутствуют Explicit Waits и класс WebDriverWait ?
Вот вроде бы информация по C# :

Или я чего-то не знаю?


(Lelik) #8

Спасибо @Noksa, чуть упростила, и с крутилкой справилась