tjx5zg
Last Updated: January 09, 2017
·
12.89K
· danhaller
5533e96a4ba30f74278018e515ff5be1

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.

Say Thanks
Respond

5 Responses
Add your response

11178
Profile wedding normal

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

over 1 year ago ·
11404
Me 3

in the same spec file

over 1 year ago ·
15684
F608652ca5cb662b40ac8ef30e0228a6

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

over 1 year ago ·
27461

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

over 1 year ago ·
28465

How can use this Page object model

11 months ago ·