Временный элемент CSS скрывает элемент xpath, на который я хочу щелкнуть.
Используя Selenium в Visual Studio, я пишу тестовый пример, в котором нужно щелкнуть элемент. Но когда я запускаю этот тестовый пример, я получаю сообщение об ошибке, говорящее мне:
OpenQA.Selenium.ElementClickInterceptedException Element <a href = "#/app/customer/handling/devices"> is not clickable at point (105,221) because another element <div class = "showbox layout-align-center-center layout-row ng-star-inserted"> obscures it
Скрывающий элемент кажется элементом CSS. Но когда я вручную перехожу на эту страницу, проверяю код и ищу этот элемент css.
<div class = "showbox layout-align-center-center layout-row ng-star-inserted"> Никаких результатов.
Поэтому я предполагаю, что этот элемент CSS является временным и может быть идентифицирован только в течение нескольких секунд, пока загружается страница. Это предположение подтверждается тем фактом, что если я поставлю статический метод ожидания Task.Delay(4000).Wait(); в этот тесткейс, я смогу завершить этот тесткейс.
Но меня не интересует решение, в котором я использую статический метод ожидания в своем коде. Я хочу иметь возможность дождаться исчезновения временного css, чтобы я мог щелкнуть нужный элемент xpath.
Это мой код:
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
wait.Until(ExpectedConditions.ElementIsVisible(By.CssSelector("div class='showbox layout-align-center-center layout-row ng-star-inserted'")));
//Waiting for temporary CSS element to be visible
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.CssSelector("div class='showbox layout-align-center-center layout-row ng-star-inserted'")));
//Waiting for temporary CSS element to disappear
wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("//div/div[2]/nav[2]/div/ul/li[1]/a"))).Click();
//Click on "Handle Tools" link
Как вы можете прочитать по комментариям в моем коде, здесь я делаю три вещи:
1. I wait for the temporary CSS to be loaded
2. I wait for it to disappear
3. I click on the xpath element.
Когда я это делаю, я получаю сообщение об ошибке, сообщающее мне, что селектор CSS, который я пытаюсь найти, недействителен.
Если я пропущу первый шаг и просто подожду, пока CSS исчезнет / станет «невидимым», он проверит это слишком быстро и проверит, прежде чем элемент CSS начнет загружаться.
Так что либо я не правильно пишу формат By.CssSelector. Или элемент CSS называется иначе, чем его вызывает Visual Studio в сообщении об ошибке, которое я цитировал выше.
Поэтому, пожалуйста, скажите мне, если я использую неправильный способ определения этого элемента CSS здесь:
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.CssSelector("div class='showbox layout-align-center-center layout-row ng-star-inserted'")));
ИЛИ
Есть ли другой способ динамического ожидания временных элементов CSS?
ИЛИ
Могу ли я как-то подтвердить, что имя скрытого элемента CSS на самом деле называется «div class = 'showbox layout-align-center-center layout-row ng-star-inserted'»?





Поэтому я не уверен на 100%, что вы подразумеваете под элементом CSS. Но я думаю, что это просто неправильное название, которое вы, возможно, подхватили. Но CSS — это каскадные таблицы стилей. Именно разметка определяет внешний вид элемента объектной модели документа (DOM).
XPath — это подход к определению местоположения элемента, чтобы драйвер мог найти его и взаимодействовать с ним. Селекторы Css — это альтернативный подход к поиску элементов в xml или html модели DOM. Таким образом, нет таких вещей, как «элемент Css» или «элемент XPath». Это всего лишь «элементы».
Что касается устранения проблемы, которую вы видите, вы можете попробовать следующее:
//This is called an extension method. It adds methods to an existing class. This should go in a static class that is accessible to your driver.
private static void WaitUntil(this IWebDriver driver, Func<bool> Condition, float timeout)
{
float timer = timeout;
while (!Condition.Invoke() && timer > 0f)
{
System.Threading.Thread.Sleep(500);
timer -= 0.5f;
}
System.Threading.Thread.Sleep(500);
}
driver.WaitUntil(() => driver.FindElementsBy(By.CssSelector(".showbox.layout-align-center-center.layout-row.ng-star-inserted").length == 0);
Также следует отметить, что ваши селекторы CSS в вашем описании полностью недействительны. Я предлагаю прочитать о них в учебник, как этот.
Я согласен со всем, вплоть до вашего кода. Основная проблема заключается в том, что если для появления всплывающего окна требуется доля секунды, ваше ожидание пройдет и продолжится, и у OP все еще будет та же проблема. Его подход был правильным, но его селекторы CSS недействительны.
Этот код будет работать нормально. Если для появления требуется время, есть альтернативные способы дождаться его, как дополнительный шаг. Я не говорю, что его код не подходит для использования ожидания Selenium. Я просто показываю ему, чем пользуюсь. То, что я использую, допускает любое логическое условие. Не только в конкретных условиях Selenium, поэтому используйте его.
Существует состояние гонки при первом входе в метод WaitUntil()... если всплывающее окно не видно, условие будет пройдено, и оно провалится, а затем, возможно, столкнется с всплывающим окном. Вы ИМЕЮТ ждете, пока всплывающее окно станет видимым, а затем невидимым, чтобы удалить это состояние гонки.
Да, ты только что это сказал. И сказал, что можно просто добавить одну дополнительную строку кода, чтобы справиться с этой возможностью. Строка для ожидания его существования, а затем добавьте вторую строку для ожидания того, что он больше НЕ существует. И можно пройти в короткое время ожидания, чтобы справиться с его появлением. Подождите 1 секунду, пока он не появится. Например, подождите 5 секунд, чтобы он не существовал. Это не сложно обойти с моим примером выше. И все ваше утверждение о том, почему это не работает, в любом случае основано на предположении. В любом случае, это легко обойти.
... и все же вы до сих пор не исправили свой ответ. Вы не ждете, когда он появится и исчезнет, вы просто ждете, когда он появится count == 0, что может произойти при первом проходе еще до того, как элемент существует. Если вы это понимаете, почему бы вам не исправить свой ответ?
Я не меняю свой ответ на основе вашего комментария «ну, предположим, что его затемняющий элемент работает таким образом», когда нет никаких доказательств того, что это так. Пожалуйста, не стесняйтесь ответить ему сами, если мой ответ вас не удовлетворит. Основываясь на представленных доказательствах, кажется, что элемент существует в состоянии готовности DOM, что и обрабатывается.
Нет, так работают ВСЕ подобные элементы. Есть шанс, что ваш код выполнит проверку до появления элемента. Вот почему это называется состоянием гонки. Вы можете оставить все как есть и надеяться, что оно никогда не подведет, и вы не поймете, почему, или вы можете сделать это правильно и никогда не беспокоиться об этом. Я думаю, это ваш выбор.
«Нет, так работают ВСЕ подобные элементы». Что я сказал о «всех» элементах? Состояние гонки — это когда потоку кода требуется информация, которую обычно предоставляет второй поток, но из-за процессорного времени она может не предоставляться к тому времени, когда первый поток достигает рассматриваемой операции.
Я не собираюсь спорить об этом. Как я уже сказал, я не собираюсь продолжать делать обновления, основанные на том, что «что, если это работает так, даже если нет никаких доказательств того, что это так». Я дал им ответ, который будет работать для них. Они могут модифицировать и использовать его так, как им нужно. Я не могу справиться с каждой перестановкой или возможностью вокруг этого. Все, что я могу сделать, это ответить на него, основываясь на информации, предоставленной мне. Спасибо, что указали на ваши опасения. Это полезно отметить, поэтому я благодарю вас. Но в то же время я не обязан делать то, чего вы от меня ожидаете.
"ВСЕ элементы так"... означает веб-страницы, которые содержат элементы, запускающие всплывающие окна. Ваше определение состояния гонки слишком специфично. См. фактическое определение. Условия гонки могут включать и другие вещи, как я описал. Если страница работает медленно, ваш код может проверить наличие всплывающего окна перед его запуском. Я чувствую, что продолжаю повторяться снова и снова... прочитайте мои комментарии выше.
Проблема в этом случае заключалась в том, что мой селектор CSS действительно был недействителен. Удаление "div class=" в начале и добавление "." решил проблему.
До:
"div class='showbox layout-align-center-center layout-row ng-star-inserted'"
После:
".showbox.layout-align-center-center.layout-row.ng-star-inserted"
Спасибо Asyranok за предоставление мне правильного формата для моего селектора CSS. В этом случае мне не понадобился остальной ваш код, вместо этого я просто скопировал правильный формат CSS из вашего кода в свое решение, и это сработало. :)
Обычно я использую xpath только при попытке идентифицировать элемент, поэтому я не привык к CSS и тому, какой формат использовать.
Также спасибо JeffC за подтверждение моего подозрения, что мне нужно дождаться первой загрузки закрывающего элемента, а тогда снова дождаться его исчезновения.
Просто к сведению. Вы можете использовать Javascript, чтобы щелкнуть элемент, когда возникает такая проблема.