Hi i have a ExtJS based UI. I have come to know that in ExtJS the combo box is not a real combo box but a combination of input text field, image of drop down box and a list. Now i am able to identify the control but i am stuck at selecting the value from the list. In the HTML source i see that the list is appearing as a seperate div and gets attached at the end of the source when we click on the drop down. find below the HTML source of the drop down control.
{
<div id="ext-gen678" class="x-form-field-wrap x-form-btn-plugin-wrap" style="width: 556px;">
<div id="ext-gen676" class="x-form-field-wrap x-form-field-trigger-wrap x-trigger-wrap-focus" style="width: 521px;">
<input id="ext-gen677" type="hidden" name="GHVOg:#concat#~inputFld~ISGP_UNIV:ft_t_isgp.prnt_iss_grp_oid:0" value="">
<input id="GHVOg:Mixh8:0" class="x-form-text x-form-field gs_dropDown_input gs_req x-form-invalid x-form-focus" type="text" autocomplete="off" size="24" style="width: 504px;">
<img id="trigger-GHVOg:Mixh8:0" class="x-form-trigger x-form-arrow-trigger" alt="" src="../../ext/resources/images/default/s.gif">
}
find below the HTML source of the drop down list:
<div id="ext-gen726" class="x-layer x-combo-list x-resizable-pinned" style="position: absolute; z-index: 12007; visibility: visible; left: 294px; top: 370px; width: 554px; height: 123px; font-size: 11px;">
<div id="ext-gen727" class="x-combo-list-inner" style="width: 554px; margin-bottom: 8px; height: 114px;">
<div class="x-combo-list-item"></div>
<div class="x-combo-list-item">12h Universe</div>
<div class="x-combo-list-item">1h Universe</div>
<div class="x-combo-list-item">24h Universe</div>
<div class="x-combo-list-item">2h Universe</div>
<div class="x-combo-list-item x-combo-selected">4h Universe</div>
Now i have problem selecting the value from the list as the div element of the list is not attached to the control.
Also please refer the screen shot, where i have multiple similar controls [Named "Add Security to Universe"]
In the screen shot you can see multiple drop downs [Add security to Universe] highlighted and all the drop downs have same value appearing in the list. so how can i identify these values from the drop down list.
I was wondering how ExtJS maintains mapping of the drop down div elements with the combo Box widget so that i could use the same logic for identifying the list. Can anyone tell me how can i go about doing this thing in selenium webdriver?
Did you notice that there will be only one visible x-combo-list
on the page? (Let me know if you can open up two combo lists at the same time)
Therefore you only need to care about the visible one x-combo-list
.
Css selector: .x-combo-list[style*='visibility: visible;'] .x-combo-list-item
Xpath: //*[contains(@class, 'x-combo-list') and contains(@style, 'visibility: visible;')]//*[contains(@class, 'x-combo-list-item')]
// untested java code, just for the logic
public void clickComboItem(WebElement input, String target) {
input.click(); // click input to pop up the combo list
List<WebElement> comboItems = driver.findElements(By.cssSelector(".x-combo-list[style*='visibility: visible;'] .x-combo-list-item"));
for (int i = 0; i <= comboItems.size(); i++) {
WebElement item = comboItems.get(i);
if (item.getText().eqauls(target)) {
item.click();
break;
}
}
}
// compilable C# version
public void ClickComboItem(IWebElement input, string target) {
input.Click();
IList<IWebElement> comboItems = driver.findElements(By.CssSelector(".x-combo-list[style*='visibility: visible;'] .x-combo-list-item"));
comboItems.First(item => item.Text.Trim() == target).Click();
}
What i can suggest is :
you catch all your inputs like :
List<WebElement> inputList = driver.findElements(By.cssSelector("input cssSelector")); // you must complete this cssSelector
WebElement input = inputList.get(0); // get the 1st input
input.click(); //click on the first input and the option list appears.
you catch all "options" like :
List<WebElement> optionList = driver.findElements(By.cssSelector(".x-combo-list-item")); // get all options
WebElement option = optionList.get(1);
option.click();
input.sendKeys(option.getText()); //getText() get the html inner value
This is just an example in Java and you can actually use a loop foreach
if you want to automat this populate for all your inputs
.
I use JavaScriptExecutor, my SelectRandomOption looks like this:
public void SelectRandomOption()
{
String randomOptionIndex = "Math.floor(Math.random()*Ext.getCmp('" + ExtJSIdOfComboBox + "').getStore().getCount()-1)";
String randomOptionValue = "Ext.getCmp('" + ExtJSIdOfComboBox + "').getStore().getAt(" + randomOptionIndex + ").getData()['model']";
String jsScript = "Ext.getCmp('" + ExtJSIdOfComboBox + "').setValue(" + randomOptionValue + ");";
js.ExecuteScript(jsScript);
}
I basically used the marked answer above however it needed a bit of adapting for Ext Js 4.1.
It's essentially the same approach but you need to look for a visible div marked with class "x-boundlist"
I used xpath and used queries that looked something like this:
.//div[@class[contains(.,'x-boundlist')]]
and then retrieve and click on an li matching your desired entry:
.//li[normalize-space(text())='combobox entry text']
I've put normalize-space in there as xpath seems to have real problems if you dont trim strings. That methods does a left + right trim and also removes duplicate spaces eg
' blah blah '
would change to 'blah blah'
.