How to select option in drop down protractorjs e2e tests

JavascriptAngularjsSeleniumTestingProtractor

Javascript Problem Overview


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.

Javascript Solutions


Solution 1 - Javascript

For me worked like a charm

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

Solution 2 - Javascript

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

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: https://stackoverflow.com/questions/28723419/select-option-abstraction.


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

Solution 4 - Javascript

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

Solution 5 - Javascript

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

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

Solution 6 - Javascript

This is how i did my selection.

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

Solution 7 - Javascript

Here's how I did it:

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

Solution 8 - Javascript

Try this, it is working for me:

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

Solution 9 - Javascript

You can try this hope it will work

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

Solution 10 - Javascript

Another way to set an option element:

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

Solution 11 - Javascript

To select items (options) with unique ids like in here:

<select
    ng-model="foo" 
    ng-options="bar as bar.title for bar in bars track by bar.id">
</select>

I'm using this:

element(by.css('[value="' + neededBarId+ '"]')).click();

Solution 12 - Javascript

We wrote a library which includes 3 ways to select an option:

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>

Additional feature of this functions is that they wait for the element to be displayed before any action on the select is performed.

You can find it on npm @hetznercloud/protractor-test-helper. Typings for TypeScript are provided as well.

Solution 13 - Javascript

Maybe not super elegant, but efficient:

function selectOption(modelSelector, index) {
    for (var i=0; i<index; i++){
        element(by.model(modelSelector)).sendKeys("\uE015");
    }
}

This just sends key down on the select you want, in our case, we are using modelSelector but obviously you can use any other selector.

Then in my page object model:

selectMyOption: function (optionNum) {
       selectOption('myOption', optionNum)
}

And from the test:

myPage.selectMyOption(1);

Solution 14 - Javascript

The problem is that solutions that work on regular angular select boxes do not work with Angular Material md-select and md-option using protractor. This one was posted by another, but it worked for me and I am unable to comment on his post yet (only 23 rep points). Also, I cleaned it up a bit, instead of browser.sleep, I used 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
});

Solution 15 - Javascript

There's an issue with selecting options in Firefox that Droogans's hack fixes that I want to mention here explicitly, hoping it might save someone some trouble: https://github.com/angular/protractor/issues/480.

Even if your tests are passing locally with Firefox, you might find that they're failing on CircleCI or TravisCI or whatever you're using for CI&deployment. Being aware of this problem from the beginning would have saved me a lot of time:)

Solution 16 - Javascript

I've been trawling the net for an answer on how to select an option in a model dropdown and i've used this combination which has helped me out with Angular material.

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

it appears that when throwing the code all in one line it could find the element in the dropdown.

Took a lot of time for this solution I hope that this helps someone out.

Solution 17 - Javascript

Helper to set the an option element:

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

Solution 18 - Javascript

If below is the given dropdown-

            <select ng-model="operator">
            <option value="name">Addition</option>
            <option value="age">Division</option>
            </select>

Then protractorjs code can be-

        var operators=element(by.model('operator'));
    		operators.$('[value=Addition]').click();

Source-https://github.com/angular/protractor/issues/600

Solution 19 - Javascript

Select option by Index:

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

Solution 20 - Javascript

I've improved a bit the solution written by PaulL. First of all I fixed the code to be compatible with the last Protractor API. And then I declare the function in 'onPrepare' section of a Protractor config file as a member of the browser instance, so it can be referenced form any e2e spec.

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

Solution 21 - Javascript

The below example is the easiest way . I have tested and passed in Protractor Version 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

Full code

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

  });
});

Solution 22 - Javascript

If none of the answer's above worked for you, try this

works with async/await too

For selecting options by text

let textOption = "option2"
await element(by.whichever('YOUR_DROPDOWN_SELECTOR'))
  .getWebElement()
  .findElement(by.xpath(`.//option[text()="${textOption}"]`))
  .click();

or by number

let optionNumber = 2
await element(by.whichever('YOUR_DROPDOWN_SELECTOR'))
  .getWebElement()
  .findElement(by.xpath(`.//option[${optionNumber}]`))
  .click();

Of course you may need to modify the xpath of child options

Don't ask me why, but this is the only way I could automate my dropdowns, when I lost hope already


Update

There was actually one case when even this approach didnt work. THe work around was a bit ugly but worked. I simply had to select the value two times

Solution 23 - Javascript

We wanted to use the elegant solution up there using angularjs material but it didnt work because there are actually no option / md-option tags in the DOM until the md-select has been clicked. So the "elegant" way didn't work for us (note angular material!) Here is what we did for it instead, don't know if its the best way but its definately working now

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

We needed to have 4 selects selected and while the select is open, there is an overlay in the way of selecting the next select. thats why we need to wait 500ms to make sure we don't get into trouble with the material effects still being in action.

Solution 24 - Javascript

Another way to set an option element:

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

Solution 25 - Javascript

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


});

Solution 26 - Javascript

You can select dropdown options by value: $('#locregion').$('[value="1"]').click();

Solution 27 - Javascript

Here is how to do it by either option value or index. This example is a bit crude, but it shows how to do what you want:

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

Solution 28 - Javascript

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

Solution 29 - Javascript

We can create a custom DropDown class for this and add a method as:

async selectSingleValue(value: string) {
        await this.element.element(by.xpath('.//option[normalize-space(.)=\'' + value + '\']')).click();
    }

Also, to verify what value is currently selected, we can have:

async getSelectedValues() {
        return await this.element.$('option:checked').getText();
    }

Solution 30 - Javascript

This is a simple one line answer in which angular has special locator which can help to select and index from list.

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

Solution 31 - Javascript

This worked fine for Angular Material

element(by.css("mat-select[formcontrolname=myMatSelect]")).sendKeys(valueToSet);

It should not set the "valueToSet" if it's not present in your options.

Solution 32 - Javascript

The simplest method to select an option using the index I have found is,

var selectDropdownElement = await element(by.xpath("Some Xpath"));
                await selectDropdownElement.all(by.tagName('option')).then(function (options) {
                        options[index].click();
                });

'index' is the option number which you want to click

Solution 33 - Javascript

Select the option by CSS property

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

or

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

Where locregion(id), organization.parent_id(model name) are the attributes of select element.

Solution 34 - Javascript

You can select drop down options like this:

element(by.xpath(
'//*[@id="locregion"]//option[contains(text(),"Ranjans Mobile Testing")]'
)).click();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRanjan BhambrooView Question on Stackoverflow
Solution 1 - JavascriptFatzView Answer on Stackoverflow
Solution 2 - JavascriptPaulLView Answer on Stackoverflow
Solution 3 - JavascriptalecxeView Answer on Stackoverflow
Solution 4 - JavascriptSandesh DanwaleView Answer on Stackoverflow
Solution 5 - JavascriptbekiteView Answer on Stackoverflow
Solution 6 - JavascriptXotabu4View Answer on Stackoverflow
Solution 7 - JavascriptyurisichView Answer on Stackoverflow
Solution 8 - JavascriptJaveedView Answer on Stackoverflow
Solution 9 - JavascriptZahid AfaqueView Answer on Stackoverflow
Solution 10 - Javascriptsurya narayana raju gView Answer on Stackoverflow
Solution 11 - JavascriptVladiusView Answer on Stackoverflow
Solution 12 - JavascriptcrashbusView Answer on Stackoverflow
Solution 13 - JavascriptCalahadView Answer on Stackoverflow
Solution 14 - JavascriptpeterhendrickView Answer on Stackoverflow
Solution 15 - JavascriptJulia JacobsView Answer on Stackoverflow
Solution 16 - Javascripttony2tonesView Answer on Stackoverflow
Solution 17 - JavascriptAdnan GhaffarView Answer on Stackoverflow
Solution 18 - JavascriptAjay PatilView Answer on Stackoverflow
Solution 19 - JavascriptShardulView Answer on Stackoverflow
Solution 20 - JavascripttrunikovView Answer on Stackoverflow
Solution 21 - JavascriptSameera De SilvaView Answer on Stackoverflow
Solution 22 - JavascriptSergey PleshakovView Answer on Stackoverflow
Solution 23 - JavascriptpascalwhoopView Answer on Stackoverflow
Solution 24 - Javascriptflaviomeira10View Answer on Stackoverflow
Solution 25 - JavascriptPramod DuttaView Answer on Stackoverflow
Solution 26 - JavascriptSander LepikView Answer on Stackoverflow
Solution 27 - JavascriptKVarmarkView Answer on Stackoverflow
Solution 28 - JavascriptJaved AliView Answer on Stackoverflow
Solution 29 - JavascriptAishwarya VatsaView Answer on Stackoverflow
Solution 30 - JavascriptVaibhav DixitView Answer on Stackoverflow
Solution 31 - JavascriptSaad JoudiView Answer on Stackoverflow
Solution 32 - JavascriptsarathView Answer on Stackoverflow
Solution 33 - JavascriptKanhaiya KumarView Answer on Stackoverflow
Solution 34 - JavascriptVinod KumarView Answer on Stackoverflow