Last Updated: January 09, 2017
·
20.88K
· danhaller

Selecting a dropdown option with webdriverjs

I've been working on an AngularJS project recently, using Protractor to do end-to-end testing. Protractor uses webdriverjs to drive the browser, which doesn't have a great deal of documentation and its built in features are quite primitive - which is one of the reasons why webdriver in other languages often has an abstraction layer built on top of it (Capybara etc).

One thing that I found way harder than it should have been is clicking an item from a dropdown box/select list, so I'll share the code here:

function selectOption(selector, item){
    var selectList, desiredOption;

    selectList = this.findElement(selector);
    selectList.click();

    selectList.findElements(protractor.By.tagName('option'))
        .then(function findMatchingOption(options){
            options.some(function(option){
                option.getText().then(function doesOptionMatch(text){
                    if (item === text){
                        desiredOption = option;
                        return true;
                    }
                });
            });
        })
        .then(function clickOption(){
            if (desiredOption){
                desiredOption.click();
            }
        });
}

This is a select item function that I can use like this:

var browser = protractor.getInstance();
browser.selectOption = selectOption.bind(browser);
browser.selectOption(protractor.By.id('my-dropdown'), 'My Value');

The key thing here is that there must be a second "then". While you can click an option in the doesOptionMatch function, clicking an option hides the rest of the options on the page which makes them stale to webdriverjs. This will cause an exception to be thrown if the doesOptionMatch function is still executing using one of the other options. The second "then" waits for the first one to complete so we don't have this problem.

Another thing worth pointing out is that if you do a find elements by tag name "option" at the browser level, it will return the options for every dropdown on the page, even if they are not visible. That seems a little inconsistent with the above - where hidden options become stale - and it's the reason that the code does the findElements against the dropdown itself, instead of the browser.

5 Responses
Add your response

Where do you define this function so that it can be called on an instance of protractor?

over 1 year ago ·

in the same spec file

over 1 year ago ·

@twittheknife, you can also put this function in a separate module http://stackoverflow.com/a/24783822/1689049

over 1 year ago ·

what does options.some refers to in the above piece of code?

over 1 year ago ·

How can use this Page object model

over 1 year ago ·