Как добавить одиночное ожидание двух разных элементов в Selenium [C #] - PullRequest
0 голосов
/ 14 сентября 2018

У меня есть две разные формы в моем приложении, и загрузку входных данных формы можно выполнить с помощью предварительно определенного шаблона, который доступен в пользовательском интерфейсе (т. Е. Значение поля ввода текста будет предварительно заполнено на основе выбора шаблона).Когда происходит загрузка данных, рендеринг элемента не произойдет, и будет заполнено только значение поля ввода.Чтобы подтвердить загрузку данных, я использую ожидание, как показано ниже:

var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(60));

wait.Until(x => x.FindElement(By.XPath(Element1_FieldXPath)).GetAttribute("value").Length > 1);

. В любой момент времени будет видна только одна Форма 1 или Форма 2.Итак, мне нужно подтвердить загрузку данных либо в Form1, либо в Form2.Итак, мне нужно написать общий метод для решения этой ситуации, и я столкнулся с приведенным ниже решением,

public bool IsDataLoadingCompleted()
{
   var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(60));

   try
   {
       wait.Until(x => x.FindElement(By.XPath(Form1_FieldXPath)).GetAttribute("value").Length > 1);
       return true;
   }
   catch (TimeoutException)
   {
       try
       {
           wait.Until(x => x.FindElement(By.XPath(Form2_FieldXPath)).GetAttribute("value").Length > 1);
           return true;
       }
       catch (TimeoutException)
       {
           return false;
       }
   }      
}

В моем решении время ожидания в худшем случае составляет 120s, когда форма 2 видна вUI.Мне нужно решить вышеупомянутую проблему с одним ожиданием вместо двойного ожидания.

Есть ли другой способ решить проблему с минимальным временем ожидания?

Пример HTML:

Форма 1 - Поле 1 HTML:

<div class="form-group field field-string">
    <label class="control-label" for="root_employeeName">Employee name</label>
    <input class="form-control" id="root_employeeName" label="Employee name" placeholder="" type="text" value="">
</div>

Форма 2 - Поле 1 HTML:

<div class="form-group field field-string">
    <label class="control-label" for="root_employeeAddress">Employee Address</label>
    <input class="form-control" id="root_employeeAddress" label="Employee Address" placeholder="" type="text" value="">
</div>

Ответы [ 3 ]

0 голосов
/ 14 сентября 2018

Вы можете решить эту проблему, используя задачи, выполняемые параллельно.Требуемый код будет выглядеть примерно так, как показано ниже, где Task.WaitAny делает свое дело.

public static bool WaitUntilOneFormLoaded(IWebDriver driver)
{
    var task1 = IsFormLoadedAsync(driver, "//some/xpath1");
    var task2 = IsFormLoadedAsync(driver, "//some/xpath2");
    Task.WaitAny(task1, task2);
    var completedTask = Task.WaitAny(task1, task2);
    switch (completedTask)
    {
        case 0: return task1.Result;
        case 1: return task2.Result;
        default: return false; // Timeout
    }
}

public static Task<bool> IsFormLoadedAsync(IWebDriver driver, string xpath)
{
    return Task.Run(() =>
    {
        try
        {
            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(60));
            wait.Until(x => driver.FindElement(By.XPath(xpath)).GetAttribute("value").Length > 1);
            return true;
        }
        catch (TimeoutException)
        {
            return false;
        }
    });
}
0 голосов
/ 14 сентября 2018

Вы можете разделить запятыми CssSelectors , чтобы построить OR логику, и вы можете использовать любое из следующих решений:

  • CSS_SELECTOR A:

    new WebDriverWait(_driver, TimeSpan.FromSeconds(120)).Until(ExpectedConditions.ElementToBeClickable(By.CssSelector('#root_employeeName, #root_employeeAddress')));
    
  • CSS_SELECTOR B:

    new WebDriverWait(_driver, TimeSpan.FromSeconds(120)).Until(ExpectedConditions.ElementToBeClickable(By.CssSelector("label[for='root_employeeName'], label[for='root_employeeAddress']")));
    
  • Ссылку можно найти в Группы селекторов

Рабочий код:

public bool IsDataLoadingCompleted(){

    var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(60));
    try
    {
        wait.Until(x => x.FindElement(By.CssSelector("[label='Form1_Field'],[label='Form1_Field']")).GetAttribute("value").Length > 1);
        return true;
    }
    catch (TimeoutException)
    {
        return false;
    }
}
0 голосов
/ 14 сентября 2018

Я предполагаю, что одна форма всегда отображается и локаторы имеют статический id

var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(60));
wait.Until(ExpectedConditions.ElementExists(By.CssSelector("input[class='form-control']")))
string elementid = FindElement(By.CssSelector("input[class='form-control']")).GetAttribute("id") // or GetAttribute("label") 
if(elementid=="root_employeeName"){
 // do your action here if name form is displayed
}
else if(elementid=="root_employeeAddress"){
// do you action here if Address form is displayed
}
...