How to select option in drop down protractorjs e2e tests

168,313

Solution 1

I had a similar problem, and eventually wrote a helper function that selects dropdown values.

I eventually decided that I was fine selecting by option number, and therefore wrote a method that takes an element and the optionNumber, and selects that optionNumber. If the optionNumber is null it selects nothing (leaving the dropdown unselected).

var selectDropdownbyNum = function ( element, optionNum ) {
  if (optionNum){
    var options = element.all(by.tagName('option'))   
      .then(function(options){
        options[optionNum].click();
      });
  }
};

I wrote a blog post if you want more detail, it also covers verifying the text of the selected option in a dropdown: http://technpol.wordpress.com/2013/12/01/protractor-and-dropdowns-validation/

Solution 2

For me worked like a charm

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

Solution 3

An elegant approach would involve making an abstraction similar to what other selenium language bindings offer out-of-the-box (e.g. Select class in Python or Java).

Let's make a convenient wrapper and hide implementation details inside:

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;

Usage example (note how readable and easy-to-use it is):

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

Solution taken from the following topic: Select -> option abstraction.


FYI, created a feature request: Select -> option abstraction.

Solution 4

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

Solution 5

To access a specific option you need to provide the nth-child() selector:

ptor.findElement(protractor.By.css('select option:nth-child(1)')).click();
Share:
168,313
Ranjan Bhambroo
Author by

Ranjan Bhambroo

Updated on July 28, 2021

Comments

  • Ranjan Bhambroo
    Ranjan Bhambroo almost 3 years

    I am trying to select an option from a drop down for the angular e2e tests using protractor.

    Here is the code snippet of the select option:

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

    I have tried:

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

    This gives me the following error:

    An invalid or illegal string was specified Build info: version: '2.35.0', revision: 'c916b9d', time: '2013-08-12 15:42:01' System info: os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.9', java.version: '1.6.0_65' Driver info: driver.version: unknown

    I have also tried:

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

    This gives me the following error:

    ElementNotVisibleError: Element is not currently visible and so may not be interacted with Command duration or timeout: 9 milliseconds Build info: version: '2.35.0', revision: 'c916b9d', time: '2013-08-12 15:42:01' System info: os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.9', java.version: '1.6.0_65' Session ID: bdeb8088-d8ad-0f49-aad9-82201c45c63f Driver info: org.openqa.selenium.firefox.FirefoxDriver Capabilities [{platform=MAC, acceptSslCerts=true, javascriptEnabled=true, browserName=firefox, rotatable=false, locationContextEnabled=true, version=24.0, cssSelectorsEnabled=true, databaseEnabled=true, handlesAlerts=true, browserConnectionEnabled=true, nativeEvents=false, webStorageEnabled=true, applicationCacheEnabled=false, takesScreenshot=true}]

    Can anyone please help me with this problem or throw some light on what i might be doing wrong here.

  • jpw
    jpw over 10 years
    This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post.
  • bekite
    bekite over 10 years
    @jpw is my answer wrong. or is it simply the formulation of my answer thats wrong?
  • jpw
    jpw over 10 years
    The formulation of an answer as a question is why. I don't know if it's the correct answer. If it is you should formulate it as such.
  • Ranjan Bhambroo
    Ranjan Bhambroo over 10 years
    @bekite Didn't work for me.Still getting the error Element Not visible error when i tried your suggestion
  • PaulL
    PaulL almost 10 years
    Minor note - v0.22 only (I just went to replace my code with this today, and had to upgrade to get it)
  • Christopher Marshall
    Christopher Marshall over 9 years
    Is there a way for targeting elements using this? Such as having duplicate State select menus.
  • Joel Kornbluh
    Joel Kornbluh over 9 years
    Christopher, ElementFinder is chain-able, so you can do: element(by.css('.specific-select')).element(by.cssContaining‌​Text('option', 'BeaverBox Testing')).click();
  • Avi Cherry
    Avi Cherry almost 9 years
    To wait for angular to finish up pending processing, use protractor's waitForAngular() method.
  • TrueWill
    TrueWill over 8 years
    Note that you can get partial matches, so 'Small' will match 'Extra Small'.
  • user115014
    user115014 over 8 years
    To add to TrueWill's comment: The down side of this solution is that if you have two similar options it will use the last found option - which threw up errors based on the wrong selection. What worked for me was stackoverflow.com/a/25333326/1945990
  • YoBre
    YoBre over 8 years
    It is the most correct for me. With cssContainingText not you make sure to capture the desired field. Just think if you have 2 selectbox with the same values. +1
  • Michiel
    Michiel over 8 years
    Why do you use 'return' in the select funtions? Is that necessary?
  • alecxe
    alecxe over 8 years
    @Michiel good point. Might be necessary if you want to explicitly resolve the promise returned by click(). Thanks.
  • Luan Nguyen
    Luan Nguyen almost 8 years
    I just use this: element(by.model('selectModel')).click(); element(by.css('md-option[value="searchOptionValue"]')).clic‌​k();
  • ESP32
    ESP32 almost 8 years
    Sorry, what is BKN01?
  • Milan Kumar
    Milan Kumar over 7 years
    @Gerfried BKN01 is the text which you want to select from the drop down.
  • Milan Kumar
    Milan Kumar over 7 years
    @GalBracha Sorry didn't get you
  • gbruins
    gbruins over 7 years
    Here's another approach: mdSelectElement.getAttribute('aria-owns').then( function(val) { let selectMenuContainer = element(by.id(val)); selectMenuContainer.element(by.css('md-option[value="foo"]')‌​).click(); } );
  • Anuj K.C.
    Anuj K.C. over 7 years
    var orderTest = element(by.model('ctrl.supplier.orderTest')) orderTest.$('[value="1"]').click(); am getting error By(css selector, [value="3"])
  • David Casillas
    David Casillas about 7 years
    Using this method the value of form.$pristine was not updated . Using the sendKeys() way worked ok for me.
  • zs2020
    zs2020 about 7 years
    If you have another option which share same prefex as BKN01, it will not work. A random one will be picked up.
  • Justin
    Justin about 6 years
    Didn't work for me, got element.findElements is not a function.
  • twm
    twm over 5 years
    If a partial match is a problem, you can use a RegExp instead of a string.
  • double-beep
    double-beep almost 4 years
    While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply. From Review
  • javafueled
    javafueled over 3 years
    This probably will not work in Angular 2+ applications where model and binding are not available. Still.
  • Sergey Pleshakov
    Sergey Pleshakov about 3 years
    even if it works, there are multiple problems with this code. 1. It's not clear why variable options is created if the output of the command is always undefined. 2. For getting one element out of elementArrayFinder, it's better (and easier) to use .get() method. 3. If you pass an element to the function, then element.all statement won't work. 4. It's better to use async functions these days. Here is an example stackoverflow.com/a/66110526/9150146