如何在 Selenium [C#] 中添加单个等待两个不同的元素
How to add the single wait for two different element in Selenium [C#]
我的应用程序中有两种不同的表单,可以使用 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:
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>
Form2 - Field1 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>
我假设始终显示一种形式并且定位器具有静态 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;
}
});
}
你可以逗号分隔 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;
}
}
我的应用程序中有两种不同的表单,可以使用 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:
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>
Form2 - Field1 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>
我假设始终显示一种形式并且定位器具有静态 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;
}
});
}
你可以逗号分隔 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;
}
}