我正在使用this HTML code:
<select name="cars" multiple>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>
</select>
手动选择一些项目。然后我想取消所有选择(我正在使用C#,但这没关系):
var carsElement = BrowserDriver.FindElementByName("cars");
var carsSelect = new SelectElement(carsElement);
carsSelect.DeselectAll();
会发生什么:首先选择的选项保持选中状态,其他选项未被选中。
请看代码,这是必须发生的事情,因为DeselectAll()
会为所有选定选项调用Click()
。您可以在浏览器中尝试。这将永远不会取消选择所有选项(除非您在单击时按住CTRL键,但Selenium代码无法做到)。因此正确的方法是将DeselectAll
更改为按How to perform Control key down in selenium webdriver?演示的同时单击CTRL
最重要的是,我知道如何解决这个问题;我的问题是:我错过了什么吗?有更容易的方法吗?是不是SelectElement
不能用于HTML SELECT多个?
答案 0 :(得分:2)
您可以肯定通过以下方式取消选择这些
browser.execute_script("[...document.querySelectorAll('[name=cars] option')].map(o => o.selected = false)")
答案 1 :(得分:0)
Select
类可以处理多项选择下拉菜单。使用DeselectAll()
时,它甚至检查下拉列表是否为多项选择。来自github
public void DeselectAll()
{
if (!this.IsMultiple)
{
throw new InvalidOperationException("You may only deselect all options if multi-select is supported");
}
foreach (IWebElement option in this.Options)
{
SetSelected(option, false);
}
}
private static void SetSelected(IWebElement option, bool select)
{
bool isSelected = option.Selected;
if ((!isSelected && select) || (isSelected && !select))
{
option.Click();
}
}
当您在不按下控制键的情况下单击第一个选择选项时,此选项将保持选中状态,但所有其他选项均被取消选择,因此实际上isSelected
和select
是false
中的SetSelected
。
解决方案是按照问题中的建议实施自己的DeselectAll()
,或者从下拉列表中选择第一个选项(这将自动取消选择所有其他选项),然后使用控件取消选择此选项。
答案 2 :(得分:0)
尽管我没有要求代码如何设置选择状态,但无论如何我都会将其发布给遇到相同问题的任何人。这是C#代码。您将需要NuGet软件包Selenium.WebDriver和Selenium.Support。 BrowserDriver
是我的助手类的成员变量,其中包含此方法。
/// <summary>
/// Sets the selection state of <paramref name="selectElement"/>. All options specified by <paramref name="selectedOptions"/>
/// are select, all others are unselected.
/// </summary>
/// <param name="selectElement">HTML select element</param>
/// <param name="selectedOptions">options to be selected</param>
internal void SelectStateByText(OpenQA.Selenium.Support.UI.SelectElement selectElement, params string[] selectedOptions)
{
Assert.IsNotNull(selectElement);
Assert.IsNotNull(selectedOptions);
CollectionAssert.IsSubsetOf(selectedOptions, selectElement.Options.Select(o => o.Text).ToArray());
if (!selectElement.IsMultiple)
{
Assert.AreEqual(1, selectedOptions.Length);
selectElement.SelectByText(selectedOptions[0]);
}
else
{
var actions = new OpenQA.Selenium.Interactions.Actions(BrowserDriver);
actions.KeyDown(Keys.LeftControl);
foreach (var option in selectElement.Options)
{
if (selectedOptions.Contains(option.Text) && !option.Selected)
{
actions.Click(option);
}
else if (option.Selected)
{
actions.Click(option);
}
}
actions.KeyUp(Keys.LeftControl).Build().Perform();
}
}
答案 3 :(得分:-1)
我已经通过 Selenium Python客户端使用deselect_all()
方法验证了您的用例,并且看来 perfecto 可行。
deselect_all()
方法清除所有选定的条目。仅在SELECT支持多个选择时有效。如果SELECT不支持多个选择,则抛出NotImplementedError。
注意:正如您在问题中提到的,我还模拟了手动
所有项目的选择代码块:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
import time
options = webdriver.ChromeOptions()
options.add_argument("start-maximized")
options.add_argument('disable-infobars')
driver=webdriver.Chrome(chrome_options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
driver.get('https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_select_multiple')
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.ID,"iframeResult")))
select_cars = Select(driver.find_element_by_css_selector("select[name='cars']"))
time.sleep(5) # Timeframe to Manually select all the items
select_cars.deselect_all()
浏览器快照: