Selenium ComboBox
Problem
I've been in the situation where I had to automate some entries to Forms. Selenium is an excellent tool but it has its flows. One of them is ComboBoxes, this also depends on how the ComboBox is implemented inside the HTML. The problem is that even though the text is written in the ComboBox (where we choose the item that we want), when you change the focus to another component then the text is erased. This problem seems to be related with how the COM is created.
Solution
The solution is to combine Win32 API calls and Selenium. We want to emulate a user entering data to the Form.
First we need to link the Win32 API calls with our class.
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
Second step is to get the WindowHandler
from the window. To do this we need to get two important data from this window. This data is constant while you're using the same form. There are alternative to get the WindowHandler
but I'm going to explain only this one.
This works for Firefox 8.0:
string titleName = myTestSelenium.getWindowName();
IntPtr windowTitlePtr = FindWindow("MozillaWindowClass", titleName);
In the first line, we're asking Selenium about the WindowsName
or title name. This is the method that I use:
public string getWindowName()
{
string retString = "";
string[] winNames = selenium.GetAllWindowTitles();
if (winNames == null)
{
return "NoName!";
}
int i=0;
while (i < winNames.Length)
{
retString += winNames[i];
i++;
}
return retString + " - Mozilla Firefox";
}
The API "FindWindow
" will return Zero if the window was not found.
Third step is to ask Selenium to focus on the ComboBox component that we need to set the entry.
selenium.Focus("id=combo_box_example_text");
Note: I suggest that you check the HTML to get all the component's IDs that are part of the ComboBox. You might need to test with different IDs until you get the correct one.
Fourth step, now we need to call the WinAPI SetForegroundWindows
.
SetForegroundWindow(windowTitlePtr);
Note: This will set the window to the front. You should not be using your PC during this step because a simple click outside the Window will cause a change in the focus window or component. I've used a VM to run the script so I can continuing using my PC ;)
Fifth step, we're now going to use a C# method called SendKeys
.
SendKeys.SendWait("TheStringThatYouWantToEnterInTheComboBox");
Note: Check Microsoft documentation about this Method.
Sixth step, just in case I've added a Sleep
step.
Thread.Sleep(THREAD_SLEEP);
I've defined THREAD_SLEEP
to 100 ms and It works perfectly.
Well that's what you need to complete a Form with tricky ComboBoxes. You can continue using Selenium after that.
Note: I suggest that when you load the Form, first take care of all ComboBoxes. Then you can continue with the rest of the components using Selenium.