如何在Selenium[C#]中添加两种不同元素的单一等待

如何在Selenium[C#]中添加两种不同元素的单一等待,c#,selenium,selenium-webdriver,css-selectors,webdriverwait,C#,Selenium,Selenium Webdriver,Css Selectors,Webdriverwait,我的应用程序中有两个不同的表单,可以使用UI中可用的预定义模板加载表单输入数据(即,输入文本字段值将根据模板选择预先填充)。当数据加载发生时,元素渲染将不会发生,只填充输入字段值。为了确认数据加载,我使用如下等待 var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(60)); wait.Until(x => x.FindElement(By.XPath(Element1_FieldXPath)).GetAttribute(

我的应用程序中有两个不同的表单,可以使用UI中可用的预定义模板加载表单输入数据(即,输入文本字段值将根据模板选择预先填充)。当数据加载发生时,元素渲染将不会发生,只填充输入字段值。为了确认数据加载,我使用如下等待

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

wait.Until(x => x.FindElement(By.XPath(Element1_FieldXPath)).GetAttribute("value").Length > 1);
在任何时候,Form1或Form2都将单独可见。因此,我需要确认在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;
       }
   }      
}
在我的解决方案中,当form2在UI中可见时,最坏的等待时间是
120s
。我需要用单等待而不是双等待来解决上述问题

有没有其他方法可以用最少的等待时间来解决问题

示例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>
<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>
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;
    }
}
Form1-Field1 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>
<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>
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;
    }
}

员工姓名
Form2-Field1 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>
<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>
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;
    }
}

员工地址

我假设始终显示一个表单,并且定位器具有静态
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
}

您可以通过使用并行运行的任务来解决这个问题。所需的代码如下所示,其中
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;
        }
    });
}
公共静态bool waituntiloneformload(IWebDriver驱动程序)
{
var task1=IsFormLoadedAsync(驱动程序“//some/xpath1”);
var task2=IsFormLoadedAsync(驱动程序“//some/xpath2”);
Task.WaitAny(task1、task2);
var completedTask=Task.WaitAny(task1,task2);
开关(已完成任务)
{
案例0:返回任务1.结果;
案例1:返回任务2.结果;
默认值:返回false;//超时
}
}
公共静态任务IsFormLoadedAsync(IWebDriver驱动程序,字符串xpath)
{
返回任务。运行(()=>
{
尝试
{
var wait=new WebDriverWait(驱动程序,TimeSpan.FromSeconds(60));
wait.Until(x=>driver.FindElement(By.XPath(XPath)).GetAttribute(“value”).Length>1);
返回true;
}
捕获(超时异常)
{
返回false;
}
});
}
您可以用逗号分隔css选择器来构造
逻辑,并且可以使用以下任一解决方案:

  • CSS\u选择器A

    new WebDriverWait(_driver, TimeSpan.FromSeconds(120)).Until(ExpectedConditions.ElementToBeClickable(By.CssSelector('#root_employeeName, #root_employeeAddress')));
    
  • CSS\u选择器B

    new WebDriverWait(_driver, TimeSpan.FromSeconds(120)).Until(ExpectedConditions.ElementToBeClickable(By.CssSelector("label[for='root_employeeName'], label[for='root_employeeAddress']")));
    
  • 您可以在中找到参考资料

工作代码:

<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>
<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>
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;
    }
}

答案取决于这些表单的定位器。你能分享表单的html代码吗?@theGuy:示例html被添加到问题中。这只在超时相等(在本例中为60秒)时有效。想象一下,当一个超时设置为30秒,另一个设置为60秒时会发生什么。这将是一个很好的解决方案。仅适用于css选择器,或者也适用于xpath、类名和链接文本?以上建议是为我制定的。我用工作代码编辑了答案