Saturday, November 21, 2015

WebDriver vs Select2

Nowadays it's quite popular to use Select2 control instead of a common one. Second version has some cool features like filtering, tagging, themes support, etc. On the other hand, sometimes it's quite hard to automate interaction with such controls due to their dynamic nature.

So what challenges do we face, while trying to access Select2 via WebDriver? First of all, we can't use existing Select wrapper to control this component anymore. The other problem is dynamic filtering: as sendKeys prints text character by character, Select2 will be constantly updating its state during typing. Besides that, we can't predict list items' loading time, as it's very dependent from collection size and performance.

We could try to play with WebDriverWait to resolve potential issues, but to be honest there're plenty of factors, which may produce an unexpected result. It's quite hard to control this component even with explicit waits technique. So how we could sort it out?

In this article I'll show how to create a custom Select2 wrapper, which will use its native API for further interaction.

We'll apply an existing template from one of my previous articles to avoid re-inventing the wheel. But first, let's take a look at Select2 native API, which we could use in our wrapper's implementation.

This is a common Select2 structure. As you can see, old select control with options' list is located below the main component. It's usually hidden. Options' values may differ from displayed text. So ideally, it'd be nice to get some option's value by visible text first. And then ask Select2 to display it.

Let's play with browser console first. Assuming that we want to select Monday from dropdown, we need to retrieve option's value, which is equal m first.

As you can see, it could be done via pure jQuery syntax.

So how we could ask Select2 to display an option, which has m value? There's a special function select2, which allows to specify different native actions like open, val, data, etc. It allows us to pass option's value directly to Select2 control for displaying Monday.

Technically, it's everything we need to reach our initial goal. Let's create Select2 wrapper now.
We're calling JavascriptExecutor internally to apply scenario we've already played with in browser console before. Our wrapper extends HTMLElement to allow using custom component directly in PageObjects without explicit initialization.
Hope it'll help you to forget about StaleElementReferenceException, while working with WebDriver and Select2. You can find sources as usual on GitHub.


  1. Great Article, want to spread it as much as possible, so, can I also publish it in ?

    1. Sure. But don't forget about a link to original article. :)