Добрый день. Хочу реализовать выбор рандомного значения в выпадающем списке. Тесты пишутся на Ruby, Selenium, Capybara, Cucumber, Site-prism.
Список представляет из себя примерно такое
<select id="things">
<option value="thing1">The First Thing</option>
<option value="thing2">The Second Thing</option>
<option value="thing3">The Third Thing</option>
</select>
Легко и просто реализуется выбор конкретного элемента,
@class.method.element.select “The First Thing”
Но это делает тест хрупким, так как элементы могут быть разными.
Хочу реализовать выбор случайного элемента, чтобы выглядело это примерно так
@class.method.element.select “element[3]”
В идеале реализовать это возможностями одного из используемых инструментов.
Значения меняются, мне нужно выбирать либо любое значение, либо к примеру первое постоянно.
Как пример на странице mail.ru форма выбора почтового домена,
#mailbox__login__domain>option
По сути точно такой же список как я привел в описании, вот только представьте, что он меняется, к примеру если вы зашли с одной страны то вам предлагают только определенные домены на выбор, с другой совершенно другие и т.д.
Могу предложить вот что:
-получить все елементы из выпадающего списка
-получить длинну полученного массива
-сгенерировать случайное число в диапазоне от 0 до длинны массива
-сделать селект элемента из массива, подставив туда рандомное число из шага 2
В руби не силён, но на .net написал бы так:
IWebDriver driver = new FirefoxDriver(); var dropDown = By.CssSelector('#things'); var things = By.XPath("//option[contains(@value, 'thing')]"); var elements = driver.FindElements(things); var length = elements.Count(); Random rnd = new Random(); var i = rnd.Next(0, length); SelectElement select = new SelectElement(dropDown ); select.SelectByText(elements[i].Text);
Вместо текста можно использовать value, например.
Или можно было бы сделать без Select’a:
IWebDriver driver = new FirefoxDriver(); var dropDown = By.CssSelector('#things'); var things = By.XPath("//option[contains(@value, 'thing')]"); driver.FindElement(dropDown ).Click(); var elements = driver.FindElements(things); var length = elements.Count(); Random rnd = new Random(); var i = rnd.Next(0, length); elements[i].Click();
Мне больше импонирует второй способ, но тут возможно нужно будет добавить ожидание после клика на выпадающий список, чтобы драйвер дождался появления всех option.
Поподробнее пожалуйста про [1..-1].sample.select_option этот кусок, если можно сразу на примере с mail.ru, который я дал выше, потому что я пробовал что-то подобное и у меня не работало
It’s not a method problem. It’s problem with locator. http://joxi.ru/KAgKdvGf6Lx0Al
This works. I try.
find(:xpath, ‘//*[@id=“mailbox-auth-login”]/div[1]’).all(:css,‘option’)[0…-1].sample.select_option
all(:css, ‘option’) - take ways to all options
[0…-1] - take option range
sample - random
select_option - choose option
element :domen, :xpath, ‘//*[@id=“mailbox-auth-login”]/div[1]’
Думаю стоит сначала получить список всех доступных значений, например так:
list = Selenum::WebDriver::Support::Select.new(@driver.find_element(list_locator))
Потом получить рандомное значение
element = list.options.sample
Теперь нужно выбрать этот самый элемент например по значению ( не самый очевидный путь, можно так же по :text и :index )
value = element.attribute(‘value’)
после чего собственно выберем элемент:
list.select_by(:value,value)
У меня есть реализация на java для случайной опции или случайного текста в селекте. Мысль та же, что у ребят выше. На вход метод принимает непосредственный родительский элемента для опций и вторым параметром либо конкретный текст, либо “rand”.
public void selectOption(WebElement element, String option) {
if (option != null && !option.equals("")) {
if (option.equals("rand")) {
Random random = new Random();
List<WebElement> options = select.getOptions();
int index = random.nextInt(options.size());
while (!options.get(index).isEnabled()) {
index = random.nextInt(options.size());
}
log.info("select option: " + options.get(index).getText());
(new WebDriverWait(driver, 5, 200).until(ExpectedConditions.visibilityOf(select);
select.selectByIndex(index);
} else {
(new WebDriverWait(driver, 5, 200).until(ExpectedConditions.visibilityOf(select));
log.info("select text: " + option);
select.selectByVisibleText(option);
}
}