Помогите пожалуйста разобраться, почему поиск элемента срабатывает через раз.
public IWebElement lblProcesses => PropertiesCollection.Driver.FindElementExt(By.XPath("//blablabla"), 20);
(по xpath находит единственный элемент без проблем, проверяла через дев тул)
У меня такой ощущение, что не ждет 20 секунд, а сразу бежит жать кнопку и даже попытки не делает.
Вопрос: как можно сделать так, что бы в случае не удачного поиска, делалась попытка найти еще раз?
public static IWebElement FindElementExt(this IWebDriver driver, By by, int timeoutInSeconds)
{
if (timeoutInSeconds > 0)
{
var attempt = 0;
try
{
var wait = new WebDriverWait(PropertiesCollection.Driver, TimeSpan.FromSeconds(timeoutInSeconds));
//return
wait.Until(Driver => Driver.FindElement(by).Displayed);
wait.Until(Driver => Driver.FindElement(by).Enabled);
}
catch (StaleElementReferenceException)
{
if (++attempt == 7)
{
Console.WriteLine(by);
throw;
}
Thread.Sleep(5);
}
}
return driver.FindElement(by);
}
}
Кнопка может быть Enabled и Displayed но иметь аттрибут “disabled = true” или какой-нибуть другой.
Попробуй посмотреть на елемент пока консоль грузится и добавь. wait.Until(d => webElement.GetAttribute(attributeName) == attributeValue);
Установите Protractor в нюгетах и заверните в него драйвер new NgWebDriver(new ChromeDriver())
Включайте синхронизацию где Angular и выключайте где не работает
Driver.IgnoreSynchronization = true;
Уберите свой try catch и используйте var wait = new DefaultWait(Driver)
в него добавьте
wait.IgnoreExceptionTypes(typeof(StaleElementReferenceException), typeof(NoSuchElementException));
Попробуйте так wait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds); wait.IgnoreExceptionTypes(typeof(StaleElementReferenceException), typeof(NoSuchElementException));
a потом wait.Until .Any() == true можно не писать а просто d.findElement(by) и засунуть прям в return
public static IWebElement FindElementExt(this IWebDriver driver, By by, int timeoutInSeconds)
{
if (timeoutInSeconds > 0)
{
var attempt = 0;
try
{
var wait = new WebDriverWait(PropertiesCollection.Driver, TimeSpan.FromSeconds(timeoutInSeconds));
wait.Until(d => driver.FindElements(by).Any() == true);
//wait.Until(Driver => Driver.FindElement(by).Displayed);
//return
//wait.Until(drv => drv.FindElement(by));
}
catch (Exception)
{
if (++attempt == 7)
{
Console.WriteLine(by);
throw;
}
Thread.Sleep(5000);
}
}
return driver.FindElement(by);
}
Этот метод работает без падений в дебаг моде. В рабочем режиме, некоторые элементы не успевают найтись и поэтому ошибка Message: OpenQA.Selenium.ElementNotVisibleException : element not interactable
** (Session info: chrome=74.0.3729.131)**
** (Driver info: chromedriver=74.0.3729.6**
Не хочется боюавлять thread.sleep();
public static IWebElement FindElementExtMES(this NgWebDriver driver1, By by, int timeoutInSeconds)
{
var wait = new DefaultWait<IWebDriver>(driver1);
wait.IgnoreExceptionTypes(typeof(StaleElementReferenceException), typeof(NoSuchElementException));
**wait.Until(d => driver1.FindElements(by));**
return driver1.FindElement(by);
}
Набросал вам полностью рабочий пример для сайта на Angular, смотрите что у вас не так. Учтите что Синхронизация по дефолту включена и ее нужно выключать на страницах без Angular. Все написано как пример, драйвер можете положить куда угодно и переделать все как вам нужно
using System;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using Protractor;
namespace Sample
{
public class Test
{
[Test]
public void SampleTest()
{
ChromeOptions option = new ChromeOptions();
option.AddArgument("no-sandbox");
WebdriverEx.Driver = new NgWebDriver(new ChromeDriver(option));
WebdriverEx.Driver.Manage().Window.Maximize();
WebdriverEx.Driver.Navigate().GoToUrl("https://angular.io/");
WebdriverEx.Driver.FindElementClickable(By.XPath("//*[@href='docs']")).Click();
WebdriverEx.Driver.FindElementVisible(By.XPath("//*[@placeholder='Search']")).SendKeys("Test Test Test");
WebdriverEx.Driver?.Quit();
}
}
public static class WebdriverEx
{
public static NgWebDriver Driver { get; set; }
public static IWebElement FindElementExist(this IWebDriver driver, By by, int timeoutInSeconds = 30)
{
var wait = new DefaultWait<IWebDriver>(driver);
wait.IgnoreExceptionTypes(typeof(StaleElementReferenceException), typeof(NoSuchElementException));
wait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
return wait.Until(d => driver.FindElement(by));
}
public static IWebElement FindElementClickable(this IWebDriver driver, By by, int timeoutInSeconds = 30)
{
var wait = new DefaultWait<IWebDriver>(driver);
wait.IgnoreExceptionTypes(typeof(StaleElementReferenceException), typeof(NoSuchElementException));
wait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
wait.Until(d => d.FindElement(by).Displayed && d.FindElement(by).Enabled);
return driver.FindElement(by);
}
public static IWebElement FindElementVisible(this IWebDriver driver, By by, int timeoutInSeconds = 30)
{
var wait = new DefaultWait<IWebDriver>(driver);
wait.IgnoreExceptionTypes(typeof(StaleElementReferenceException), typeof(NoSuchElementException));
wait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
wait.Until(d => d.FindElement(by).Displayed);
return driver.FindElement(by);
}
}
}
Мне нужно перейти в другое окно , в котором немножко другая имплементация.
В итоге ошибка
Message: OpenQA.Selenium.WebDriverException : javascript error: angular never provided resumeBootstrap
JavaScript stack:
Error: angular never provided resumeBootstrap
at check (eval at executeAsyncScript (:448:5), <anonymous>:33:15)
at eval (eval at executeAsyncScript (:448:5), <anonymous>:38:1)
at eval (eval at executeAsyncScript (:448:5), <anonymous>:38:12)
at executeAsyncScript (<anonymous>:448:26)
at <anonymous>:464:29
at callFunction (<anonymou
Там где отдаете алюру драйвер сделайте так Driver.WrappedDriver - это драйвер который вы завернули в NgDriver, и делайте так если что то не работает с NgDriver
Driver.IgnoreSynchronization = true; делайте там где angular не работает, и false - там где все ок
Если многопроблем с NgDriver, можете его вобще убрать, но стабильность немного упадет (Это касается только Angular сайтов)