Selenium DeselectAll не работает для HTML SELECT с несколькими атрибутами - PullRequest
0 голосов
/ 22 ноября 2018

Я использую этот HTML-код :

<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 на нажатие клавиши CTRL при нажатии, как это продемонстрировано Как выполнить управляющую клавишу в селеновом веб-драйвере?

В итоге, я знаю, как это исправить;мои вопросы: я что-то упустил?Есть ли более простой способ?Разве SelectElement не предназначен для множественного выбора HTML SELECT?

Ответы [ 4 ]

0 голосов
/ 22 ноября 2018

Я подтвердил ваш сценарий использования использования deselect_all() метода с помощью Selenium Python Client , и, похоже, он работает perfecto .

deselect_all ()

deselect_all() метод очищает все выбранные записи.Это действительно только тогда, когда SELECT поддерживает множественный выбор.throws NotImplementedError Если SELECT не поддерживает множественный выбор.


Иллюстрация

Примечание : Как вы упомянули в своем вопросе, я также смоделировал выбор всехэлементы вручную

  • Блок кода:

    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()
    
  • Снимок браузера:

deselect_all.gif

0 голосов
/ 22 ноября 2018

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(), как предлагается в вашем вопросе, либо выбрать первыйиз раскрывающегося списка (который автоматически отменит выбор всех остальных параметров), а затем отмените выбор этого параметра с помощью элемента управления.

0 голосов
/ 22 ноября 2018

Несмотря на то, что я не спрашивал код, как установить состояние выбора, я все равно опубликую его для всех, кто столкнулся с такой же проблемой.Это код 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();
    }
}
0 голосов
/ 22 ноября 2018

Вы можете отменить их выбор с помощью

browser.execute_script("[...document.querySelectorAll('[name=cars] option')].map(o => o.selected = false)")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...