Как выбрать опцию в выпадающих тестах protractorjs e2e
Я пытаюсь выбрать вариант из выпадающего списка для угловых испытаний e2e с использованием транспортира.
Вот фрагмент кода опции выбора:
<select id="locregion" class="create_select ng-pristine ng-invalid ng-invalid-required" required="" ng-disabled="organization.id !== undefined" ng-options="o.id as o.name for o in organizations" ng-model="organization.parent_id">
<option value="?" selected="selected"></option>
<option value="0">Ranjans Mobile Testing</option>
<option value="1">BeaverBox Testing</option>
<option value="2">BadgerBox</option>
<option value="3">CritterCase</option>
<option value="4">BoxLox</option>
<option value="5">BooBoBum</option>
</select>
Я пытался:
ptor.findElement(protractor.By.css('select option:1')).click();
Это дает мне следующую ошибку:
Указана неверная или недопустимая строка. Информация о сборке: версия: '2.35.0', версия: 'c916b9d', время: '2013-08-12 15:42:01' Информация о системе: os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.9', java.version: '1.6.0_65'Информация о драйвере: driver.version: неизвестно
Я также попробовал:
ptor.findElement(protractor.By.xpath('/html/body/div[2]/div/div[4]/div/div/div/div[3]/ng-include/div/div[2]/div/div/organization-form/form/div[2]/select/option[3]')).click();
Это дает мне следующую ошибку:
ElementNotVisibleError: Элемент в данный момент не виден и поэтому может не взаимодействовать с длительностью или временем ожидания команды: 9 миллисекунд. Информация о сборке: версия: '2.35.0', версия: 'c916b9d', время: '2013-08-12 15:42: 01 'Системная информация: os.name:' Mac OS X ', os.arch:' x86_64 ', os.version: '10.9', java.version: '1.6.0_65' Идентификатор сеанса: bdeb8088-d8ad-0f49-aad9-82201c45c63f Информация о драйвере: org.openqa.selenium.firefox.FirefoxDriver Возможности [{platform=MAC, acceptSslCerts=true, javascriptEnabled=true, browserName=firefox, rotatable=false, locationContextEnabled=true, версия =24.0, база данных =24.0, css =true, handlesAlerts=true, browserConnectionEnabled=true, nativeEvents=false, webStorageEnabled=true, applicationCacheEnabled=false, takeScreenshot=true}]
Может кто-нибудь, пожалуйста, помогите мне с этой проблемой или пролить свет на то, что я могу делать здесь не так.
34 ответа
У меня была похожая проблема, и в итоге я написал вспомогательную функцию, которая выбирает выпадающие значения.
В конце концов я решил, что у меня все в порядке, выбирая номер опции, и поэтому написал метод, который берет элемент и optionNumber и выбирает этот optionNumber. Если параметр optionNumber равен нулю, он ничего не выбирает (оставляя невыбранным выпадающее меню).
var selectDropdownbyNum = function ( element, optionNum ) {
if (optionNum){
var options = element.all(by.tagName('option'))
.then(function(options){
options[optionNum].click();
});
}
};
Я написал пост в блоге, если вы хотите получить более подробную информацию, он также включает проверку текста выбранного параметра в раскрывающемся списке: http://technpol.wordpress.com/2013/12/01/protractor-and-dropdowns-validation/
For me worked like a charm
element(by.cssContainingText('option', 'BeaverBox Testing')).click();
Надеюсь, поможет.
Элегантный подход включал бы создание абстракции, аналогичной тому, что предлагают другие привязки языка селена из коробки (например, Select
класс в Python или Java).
Давайте сделаем удобную оболочку и скроем детали реализации внутри:
var SelectWrapper = function(selector) {
this.webElement = element(selector);
};
SelectWrapper.prototype.getOptions = function() {
return this.webElement.all(by.tagName('option'));
};
SelectWrapper.prototype.getSelectedOptions = function() {
return this.webElement.all(by.css('option[selected="selected"]'));
};
SelectWrapper.prototype.selectByValue = function(value) {
return this.webElement.all(by.css('option[value="' + value + '"]')).click();
};
SelectWrapper.prototype.selectByPartialText = function(text) {
return this.webElement.all(by.cssContainingText('option', text)).click();
};
SelectWrapper.prototype.selectByText = function(text) {
return this.webElement.all(by.xpath('option[.="' + text + '"]')).click();
};
module.exports = SelectWrapper;
Пример использования (обратите внимание, насколько он читаем и прост в использовании):
var SelectWrapper = require('select-wrapper');
var mySelect = new SelectWrapper(by.id('locregion'));
# select an option by value
mySelect.selectByValue('4');
# select by visible text
mySelect.selectByText('BoxLox');
Решение взято из следующей темы: Выберите -> опция абстракция.
К вашему сведению, создан запрос объекта: выберите -> опция абстракция.
Для доступа к определенной опции вам нужно предоставить селектор nth-child():
ptor.findElement(protractor.By.css('select option:nth-child(1)')).click();
Вот как я сделал свой выбор.
function switchType(typeName) {
$('.dropdown').element(By.cssContainingText('option', typeName)).click();
};
Попробуйте это, это работает для меня:
element(by.model('formModel.client'))
.all(by.tagName('option'))
.get(120)
.click();
Вот как я это сделал:
$('select').click();
$('select option=["' + optionInputFromFunction + '"]').click();
// This looks useless but it slows down the click event
// long enough to register a change in Angular.
browser.actions().mouseDown().mouseUp().perform();
Другой способ установить элемент option:
var select = element(by.model('organization.parent_id'));
select.$('[value="1"]').click();
Вы можете попробовать эту надежду, это сработает
element.all(by.id('locregion')).then(function(selectItem) {
expect(selectItem[0].getText()).toEqual('Ranjans Mobile Testing')
selectItem[0].click(); //will click on first item
selectItem[3].click(); //will click on fourth item
});
Мы написали библиотеку, которая включает в себя 3 способа выбора варианта:
selectOption(option: ElementFinder |Locator | string, timeout?: number): Promise<void>
selectOptionByIndex(select: ElementFinder | Locator | string, index: number, timeout?: number): Promise<void>
selectOptionByText(select: ElementFinder | Locator | string, text: string, timeout?: number): Promise<void>
Дополнительная особенность этих функций заключается в том, что они ожидают отображения элемента, прежде чем предпринимать какие-либо действия с select
выполняется.
Вы можете найти его на npm https://www.npmjs.com/package/@hetznercloud/protractor-test-helper. Типы для TypeScript также предоставляются.
Чтобы выбрать элементы (варианты) с уникальными идентификаторами, как здесь:
<select
ng-model="foo"
ng-options="bar as bar.title for bar in bars track by bar.id">
</select>
Я использую это:
element(by.css('[value="' + neededBarId+ '"]')).click();
Проблема состоит в том, что решения, которые работают с обычными угловыми полями выбора, не работают с угловым материалом md-select и md-option с использованием транспортира. Этот был опубликован другим, но он сработал для меня, и я пока не могу комментировать его сообщение (всего 23 повторения). Кроме того, я немного прибрался, вместо browser.sleep, я использовал browser.waitForAngular();
element.all(by.css('md-select')).each(function (eachElement, index) {
eachElement.click(); // select the <select>
browser.waitForAngular(); // wait for the renderings to take effect
element(by.css('md-option')).click(); // select the first md-option
browser.waitForAngular(); // wait for the renderings to take effect
});
Если ни один из приведенных выше ответов не помог вам, попробуйте это
также работает с async / await
Для выбора вариантов по тексту
let textOption = "option2"
await element(by.whichever('YOUR_DROPDOWN_SELECTOR'))
.getWebElement()
.findElement(by.xpath(`.//option[text()="${textOption}"]`))
.click();
или по номеру
let optionNumber = 2
await element(by.whichever('YOUR_DROPDOWN_SELECTOR'))
.getWebElement()
.findElement(by.xpath(`.//option[${optionNumber}]`))
.click();
Конечно, вам может потребоваться изменить xpath дочерних параметров
Не спрашивайте меня, почему, но это единственный способ автоматизировать выпадающие списки, когда я уже потерял надежду
Может быть, не супер элегантный, но эффективный:
function selectOption(modelSelector, index) {
for (var i=0; i<index; i++){
element(by.model(modelSelector)).sendKeys("\uE015");
}
}
Это просто отправляет ключ вниз по желаемому выбору, в нашем случае мы используем modelSelector, но, очевидно, вы можете использовать любой другой селектор.
Тогда на моей странице объектная модель:
selectMyOption: function (optionNum) {
selectOption('myOption', optionNum)
}
И из теста:
myPage.selectMyOption(1);
Помощник для установки элемента option:
selectDropDownByText:function(optionValue) {
element(by.cssContainingText('option', optionValue)).click(); //optionValue: dropDownOption
}
Пример ниже - самый простой способ. Я протестировал и прошел версию Protractor.5.4.2
//Drop down selection using option's visibility text
element(by.model('currency')).element(by.css("[value='Dollar']")).click();
Or use this, it $ isshort form for .By.css
element(by.model('currency')).$('[value="Dollar"]').click();
//To select using index
var select = element(by.id('userSelect'));
select.$('[value="1"]').click(); // To select using the index .$ means a shortcut to .By.css
Полный код
describe('Protractor Demo App', function() {
it('should have a title', function() {
browser.driver.get('http://www.way2automation.com/angularjs-protractor/banking/#/');
expect(browser.getTitle()).toEqual('Protractor practice website - Banking App');
element(by.buttonText('Bank Manager Login')).click();
element(by.buttonText('Open Account')).click();
//Drop down selection using option's visibility text
element(by.model('currency')).element(by.css("[value='Dollar']")).click();
//This is a short form. $ in short form for .By.css
// element(by.model('currency')).$('[value="Dollar"]').click();
//To select using index
var select = element(by.id('userSelect'));
select.$('[value="1"]').click(); // To select using the index .$ means a shortcut to .By.css
element(by.buttonText("Process")).click();
browser.sleep(7500);// wait in miliseconds
browser.switchTo().alert().accept();
});
});
Если ниже дан данный выпадающий
<select ng-model="operator">
<option value="name">Addition</option>
<option value="age">Division</option>
</select>
Тогда код protractorjs может быть
var operators=element(by.model('operator'));
operators.$('[value=Addition]').click();
Я немного улучшил решение, написанное PaulL. Прежде всего я исправил код, чтобы он был совместим с последним API-интерфейсом Protractor. И затем я объявляю функцию в разделе "onPrepare" конфигурационного файла Protractor как член экземпляра браузера, так что на нее можно ссылаться из любой спецификации e2e.
onPrepare: function() {
browser._selectDropdownbyNum = function (element, optionNum) {
/* A helper function to select in a dropdown control an option
* with specified number.
*/
return element.all(by.tagName('option')).then(
function(options) {
options[optionNum].click();
});
};
},
Существует проблема с выбором опций в Firefox, которую Хак Дрооганс исправляет, о которой я хочу упомянуть здесь в явном виде, надеясь, что это может спасти кого-то от неприятностей: https://github.com/angular/protractor/issues/480.
Даже если ваши тесты проходят локально с Firefox, вы можете обнаружить, что они терпят неудачу в CircleCI или TravisCI или любом другом, который вы используете для CI и развертывания. Осознание этой проблемы с самого начала сэкономило бы мне много времени:)
Я трахал сеть за ответ о том, как выбрать опцию в выпадающем списке моделей, и я использовал эту комбинацию, которая помогла мне с материалом Angular.
element (by.model ("ModelName")). click (). element (By.xpath ('местоположение xpath')).click();
похоже, что при броске кода все в одну строку он может найти элемент в раскрывающемся списке.
Я потратил много времени на это решение, я надеюсь, что это поможет кому-то.
Выберите опцию по индексу:
var selectDropdownElement= element(by.id('select-dropdown'));
selectDropdownElement.all(by.tagName('option'))
.then(function (options) {
options[0].click();
});
Самый простой способ выбрать вариант с использованием найденного мной индекса:
var selectDropdownElement = await element(by.xpath("Some Xpath"));
await selectDropdownElement.all(by.tagName('option')).then(function (options) {
options[index].click();
});
'index' - это номер опции, которую вы хотите щелкнуть
Другой способ установить элемент option:
var setOption = function(optionToSelect) {
var select = element(by.id('locregion'));
select.click();
select.all(by.tagName('option')).filter(function(elem, index) {
return elem.getText().then(function(text) {
return text === optionToSelect;
});
}).then(function(filteredElements){
filteredElements[0].click();
});
};
// using the function
setOption('BeaverBox Testing');
----------
element.all(by.id('locregion')).then(function(Item)
{
// Item[x] = > // x is [0,1,2,3]element you want to click
Item[0].click(); //first item
Item[3].click(); // fourth item
expect(Item[0].getText()).toEqual('Ranjans Mobile Testing')
});
Вы можете выбрать параметры раскрывающегося списка по значению:$('#locregion').$('[value="1"]').click();
static selectDropdownValue(dropDownLocator,dropDownListLocator,dropDownValue){
let ListVal ='';
WebLibraryUtils.getElement('xpath',dropDownLocator).click()
WebLibraryUtils.getElements('xpath',dropDownListLocator).then(function(selectItem){
if(selectItem.length>0)
{
for( let i =0;i<=selectItem.length;i++)
{
if(selectItem[i]==dropDownValue)
{
console.log(selectItem[i])
selectItem[i].click();
}
}
}
})
}
Мы можем создать для этого собственный класс DropDown и добавить метод как:
async selectSingleValue(value: string) {
await this.element.element(by.xpath('.//option[normalize-space(.)=\'' + value + '\']')).click();
}
Кроме того, чтобы проверить, какое значение выбрано в данный момент, мы можем иметь:
async getSelectedValues() {
return await this.element.$('option:checked').getText();
}
Это простой однострочный ответ, в котором у angular есть специальный локатор, который может помочь выбрать и индексировать из списка.
element.all(by.options('o.id as o.name for o in organizations')).get(Index).click()
Вот как это сделать по значению опции или по индексу. Этот пример немного грубоват, но показывает, как сделать то, что вы хотите:
HTML:
<mat-form-field id="your-id">
<mat-select>
<mat-option [value]="1">1</mat-option>
<mat-option [value]="2">2</mat-option>
</mat-select>
</mat-form-field>
TS:
function selectOptionByOptionValue(selectFormFieldElementId, valueToFind) {
const formField = element(by.id(selectFormFieldElementId));
formField.click().then(() => {
formField.element(by.tagName('mat-select'))
.getAttribute('aria-owns').then((optionIdsString: string) => {
const optionIds = optionIdsString.split(' ');
for (let optionId of optionIds) {
const option = element(by.id(optionId));
option.getText().then((text) => {
if (text === valueToFind) {
option.click();
}
});
}
});
});
}
function selectOptionByOptionIndex(selectFormFieldElementId, index) {
const formField = element(by.id(selectFormFieldElementId));
formField.click().then(() => {
formField.element(by.tagName('mat-select'))
.getAttribute('aria-owns').then((optionIdsString: string) => {
const optionIds = optionIdsString.split(' ');
const optionId = optionIds[index];
const option = element(by.id(optionId));
option.click();
});
});
}
selectOptionByOptionValue('your-id', '1'); //selects first option
selectOptionByOptionIndex('your-id', 1); //selects second option