StaleElementException при нажатии на TableRow в угловой веб-странице

<div id="crm" class="row gridrow clickable ng-scope" ng-repeat="customer in customerList" ng-click="gotoRecord(customer.id)">
     <i class="col m1 s1 tiny fa fa-male"></i>
     <div class="col m3 s11 ng-binding"> Allard</div>
     <div class="col m2 s12 ng-binding"></div>
</div>

У меня есть этот фрагмент HTML, он отображает одну строку в результате поискового действия для Клиента с именем "Клиент" "Allard". Я хочу нажать на этого клиента, чтобы перейти к следующей странице, но в большинстве случаев это приводит к исключению StaleElementException.

Я попробовал это двумя разными способами, используя Транспортир и без Транспортира.

Первый способ:

IWebElement elem = driver.FindElement(By.XPath("//*[contains(text(),'" + nameCustomer + "')]//parent::div[contains(@id,'crm')]"));
        ExplicitWait.WaitAndClick(driver, elem);

Второй способ:

var customers = driver.FindElements(NgBy.Repeater("customer in customerList"));
        foreach (var customer in customers)
        {
            if (elem.Text.Equals(nameCustomer))
            {
                elem.Click();
            }
        }

1 ответ

Решение

Проблема (я думаю)

С помощью StaleReferenceExceptions ранее созданный IWebElement больше не подключается к DOM (вы, вероятно, уже знаете это). Скорее всего, это происходит так:
1: Вы нажимаете кнопку поиска.
2: Селен исполняет driver.FindElement(...) и находит соответствующий элемент.
3: Затем функция поиска завершается и DOM обновляется. Старый найденный ранее IWebElement исчез.
4: Затем Selenium пытается щелкнуть по элементу (который больше не существует, вызывая StaleElementException. Есть элемент, который соответствует тому, что был там ранее, но это не тот же элемент в глазах Selenium.)

Ваше утверждение о том, что это происходит "большую часть времени", заставляет меня подозревать, что это даже больше, потому что исключение будет зависеть от порядка событий, который будет варьироваться в зависимости от относительных скоростей Selenium и веб-страницы.

Как решить (если это ваша проблема)

Вам нужно найти на странице что-то, что сообщит Selenium, что поисковое действие выполнено. Вот тут-то и проявляется креативность в написании сценариев автоматизации графического интерфейса. Если на странице что-то, что, как вы знаете, изменится в результате загрузки, создайте явное ожидание, чтобы убедиться, что оно завершено. Возможно, есть полоса загрузки, которая появляется, или сообщение, которое появляется, когда поиск завершен. Вы можете получить элемент, который не соответствует вашему запросу, прежде чем щелкнуть поиск, а затем явно подождать, чтобы убедиться, что он исчезает, прежде чем искать результат, который вы ожидаете получить.

Это будет выглядеть примерно так ниже.

# Search action performed before this.
WebDriverWait wait= new WebDriverWait(driver, TimeSpan.FromSeconds(secondsToWait));
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.XPath( expressionForElementThatWillDissapear )));


IWebElement elem = driver.FindElement(By.XPath("//*[contains(text(),'" + nameCustomer + "')]//parent::div[contains(@id,'crm')]"));
            ExplicitWait.WaitAndClick(driver, elem);

Я бы рекомендовал сделать метод для реализации явного ожидания выше. Эти ситуации будут возникать часто.

Другие вопросы по тегам