Як вибрати варіант у випадаючих тестах protractorjs e2e


121

Я намагаюся вибрати варіант зі спадного меню для кутових тестів 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 'Інформація про водія: драйвер.версія: невідомо

Я також спробував:

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 Capability [{platform = MAC, acceptSslCerts = true, javascriptEnabled = true, browserName = firefox, rotatable = false, locationContextEnabled = true, версія = 24,0, cssSebleors = true, handlesAlerts = true, browserConnectionEnabled = true, nativeEvents = false, webStorageEnabled = true, applicationCacheEnabled = false, takesScreenshot = true}]

Чи хтось, будь ласка, допоможе мені з цією проблемою або кине трохи світла на те, що я можу робити тут неправильно.

Відповіді:


88

У мене була схожа проблема, і врешті-решт я написав функцію помічника, яка вибирає спадні значення.

Я врешті-решт вирішив, що я добре вибираю номер опції, і тому написав метод, який приймає елемент і optionNumber, і вибирає цей параметрNumber. Якщо параметр Number is null, він нічого не вибирає (залишаючи невибраний спадний список).

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/


1
Не працював для мене, отримав element.findElements - це не функція.
Джастін

251

Для мене працював як шарм

element(by.cssContainingText('option', 'BeaverBox Testing')).click();

Сподіваюся, це допомагає.


2
Незначна примітка - лише v0.22 (я просто пішов замінити свій код цим сьогодні, і мені довелося оновити його, щоб отримати його)
PaulL

Чи існує спосіб націлювання елементів за допомогою цього? Наприклад, з дублікатами меню вибору штату.
Крістофер Маршалл

11
Крістофер, ElementFinderє ланцюговим, тому ви можете зробити:element(by.css('.specific-select')).element(by.cssContainingText('option', 'BeaverBox Testing')).click();
Джоел Корнблух

6
Зауважте, що ви можете отримати часткові сірники, тому "Малий" буде відповідати "Надто малому".
TrueWill

3
Щоб додати коментар TrueWill: Нижньою стороною цього рішення є те, що якщо у вас є два аналогічні варіанти, він використовуватиме останній знайдений варіант - який викинув помилки на основі неправильного вибору. Що працювало для мене, це stackoverflow.com/a/25333326/1945990
Mike W

29

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

Рішення взято з наступної теми: Виберіть -> параметр абстракції .


FYI, створив запит на функцію: Виберіть -> параметр абстракції .


Чому ви використовуєте "return" у вибраних функціях? Це потрібно?
Міхель

1
@Michiel хороший момент. Можливо, це буде необхідно, якщо ви хочете прямо вирішити обіцянку, яку повернув click(). Дякую.
alecxe

20
element(by.model('parent_id')).sendKeys('BKN01');

1
Для мене це найправильніше. За допомогою cssContainText ви не переконайтеся, що захочете потрібне поле. Подумайте, якщо у вас є 2 вибірки з однаковими значеннями. +1
YoBre

4
Вибачте, що таке BKN01?
Герфрід

1
@Gerfried BKN01 - це текст, який потрібно вибрати зі спадного меню.
MilanYadav

@GalBracha Вибачте, я вас не отримав
MilanYadav

Якщо у вас є інший варіант, який має спільний префекс, як BKN01, він не працюватиме. Вибереться випадковий.
zs2020

15

Для доступу до певної опції вам потрібно надати селектор nth-child ():

ptor.findElement(protractor.By.css('select option:nth-child(1)')).click();

Це не дає відповіді на запитання. Щоб критикувати або вимагати роз'яснення у автора, залиште коментар під їх публікацією.
jpw

@jpw моя відповідь неправильна. чи це просто постановка моєї відповіді, що це неправильно?
бекіте

Формулювання відповіді як питання - чому. Я не знаю, чи це правильна відповідь. Якщо це так, то слід сформулювати його як таке.
jpw

3
@bekite не працював для мене. Доки не отримав помилку Елемент Невидима помилка, коли я спробував вашу пропозицію
Ranjan Bhambroo

8

Ось як я зробив свій вибір.

function switchType(typeName) {
     $('.dropdown').element(By.cssContainingText('option', typeName)).click();
};

5

Ось як я це зробив:

$('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();

Щоб зачекати, коли кут закінчить очікує обробку, скористайтеся waitForAngular()методом транспортира.
Avi Cherry

5

Спробуйте це, для мене це працює:

element(by.model('formModel.client'))
    .all(by.tagName('option'))
    .get(120)
    .click();

4

Ви можете спробувати цю надію, що вона спрацює

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
});

4

Ще один спосіб встановити елемент опції:

var select = element(by.model('organization.parent_id'));
select.$('[value="1"]').click();

var orderTest = елемент (by.model ('ctrl.supplier.orderTest')) orderTest. $ ('[value = "1"]'). click (); я отримую помилку Автор (css selector, [value = "3"])
Anuj KC

3

Щоб вибрати елементи (параметри) з унікальними ідентифікаторами, як тут:

<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();

3

Ми написали бібліотеку, яка містить 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 @ hetznercloud / транспортир-тест-помічник . Також передбачені типи для TypeScript.


2

Можливо, не надто елегантно, але ефективно:

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);

2

Проблема полягає в тому, що рішення, які працюють на звичайних кутових вітринах, не працюють з md-select та md-опцією Angular Material, використовуючи транспортир. Цей був опублікований іншим, але він працював на мене, і я поки не можу коментувати його повідомлення (лише 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
});

Я просто використовую це:element(by.model('selectModel')).click(); element(by.css('md-option[value="searchOptionValue"]')).click();
Luan Nguyen

Ось ще один підхід: mdSelectElement.getAttribute('aria-owns').then( function(val) { let selectMenuContainer = element(by.id(val)); selectMenuContainer.element(by.css('md-option[value="foo"]')).click(); } );
gbruins

1

У Firefox є проблема з вибором параметрів, які виправляє хак Droogans, який я хочу тут прямо згадати, сподіваючись, що це може врятувати комусь певну неприємність: https://github.com/angular/protractor/isissue/480 .

Навіть якщо ваші тести проходять локально з Firefox, ви можете виявити, що вони не спрацьовують на CircleCI або TravisCI або будь-що, що ви використовуєте для CI та розгортання. Усвідомлення цієї проблеми з самого початку врятувало б мені багато часу :)


1

Помічник у встановленні елемента опції:

selectDropDownByText:function(optionValue) {
            element(by.cssContainingText('option', optionValue)).click(); //optionValue: dropDownOption
        }

1

Якщо нижче, наведене спадне меню-

            <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();

Джерело- https://github.com/angular/protractor/isissue/600


1

Виберіть варіант за індексом:

var selectDropdownElement= element(by.id('select-dropdown'));
selectDropdownElement.all(by.tagName('option'))
      .then(function (options) {
          options[0].click();
      });

1

Я трохи вдосконалив рішення, написане 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();
        });
    };
  },

1

Я шукав мережу, щоб отримати відповідь про те, як вибрати варіант у спадному варіанті моделі, і я використав цю комбінацію, яка допомогла мені з кутовим матеріалом.

element(by.model("ModelName")).click().element(By.xpath('xpathlocation')).click();

виявляється, що при перекиданні коду в один рядок він міг знайти елемент у спадному меню.

На це рішення знадобилося багато часу, я сподіваюся, що це допоможе комусь.


0

Ми хотіли використовувати елегантне рішення там, використовуючи матеріал angularjs, але це не спрацювало, оскільки насправді в DOM немає тегів option / md-option, поки не буде натиснуто md-select. Тож "елегантний" спосіб не працював для нас (зверніть увагу на кутовий матеріал!) Ось, що ми зробили для цього замість цього, не знаю, чи це найкращий спосіб, але його зараз точно працює

element.all(by.css('md-select')).each(function (eachElement, index) {
    eachElement.click();                    // select the <select>
    browser.driver.sleep(500);              // wait for the renderings to take effect
    element(by.css('md-option')).click();   // select the first md-option
    browser.driver.sleep(500);              // wait for the renderings to take effect
});

Нам потрібно було вибрати 4 вибору, і поки вибір відкритий, є спосіб накладання наступного вибору. ось чому нам потрібно зачекати 500 м, щоб переконатися, що ми не потрапимо в проблеми з матеріальними ефектами, які все ще діють.


0

Ще один спосіб встановити елемент опції:

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');

0
----------
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')


});

0

Ви можете вибрати параметри випадаючого меню за значенням: $('#locregion').$('[value="1"]').click();


0

Ось як це зробити за значенням параметра або індексом . Цей приклад є трохи грубим, але він показує, як робити те, що ви хочете:

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

0
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();
                   }
               }            
        }

    })

}

0

Ми можемо створити для цього спеціальний клас 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();
    }

0

Наведений нижче приклад - найпростіший спосіб. Я протестував і пройшов у 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();

  });
});

0

Це простий однорядний відповідь, у якому у куті є спеціальний локатор, який може допомогти вибрати та індексувати зі списку.

element.all(by.options('o.id as o.name for o in organizations')).get(Index).click()

Хоча цей код може вирішити питання, включаючи пояснення, як і чому це вирішує проблему, справді допоможе покращити якість вашої публікації та, ймовірно, призведе до збільшення кількості голосів. Пам'ятайте, що ви відповідаєте на запитання читачів у майбутньому, а не лише про людину, яка зараз задає питання. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення та вказати, які обмеження та припущення застосовуються. З огляду
подвійний звуковий сигнал

-1

Виберіть параметр за властивістю CSS

element(by.model("organization.parent_id")).element(by.css("[value='1']")).click();

або

element(by.css("#locregion")).element(by.css("[value='1']")).click();

Де locregion (id), organization.parent_id (назва моделі) є атрибутами елемента вибору.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.