keylogger
keylogger

Reputation: 872

Selenium Webdriver cannot choose a value in a dropdown list

I am trying to implement Selenium Webdriver using Java. Basically, I have a website with a blank field. Once user click on the field, a drop-down list with 5 options will appear and user should choose one option.

The codes look like this

<!-- language: lang-html -->
<div class="default-form w-border scheduleAddFrom" style="display: block;">
<div>
<div class="section frameless nopadding nomargin" data-form-element="SectionHeading" style="min-width: 100%;">
<div class="section-body frameless nopadding nomargin">
<div class="default-form">
<div class="form-row required-message hidden" style="min-height: 25px;">
<div class="form-row print-avoid-page-break" data-form-element="FieldEdit" style="min-height: 25px;">
<label for="">Department</label>
<input id="Schedule-00-Row136153aa-9fa8-499b-8458-2b155443223bE-TaskId-Display" class="ui-autocomplete-display validate widget" type="text" autocomplete="off">
<span class="ui-autocomplete-display-icon"></span>
<div class="subhidden">
<select id="Schedule-00-Row136153aa-9fa8-499b-8458-2b155443223bE-TaskId" class="validate widget " data-default-value="" tabindex="5000" data-display-id="Schedule-00-Row136153aa-9fa8-499b-8458-2b155443223bE-TaskId-Display">
   <option value=""></option>
   <option value="OPT1">Option 1</option>
   <option value="OPT2">Option 2</option>
   <option value="OPT3">Option 3</option>
   <option value="OPT4">Option 4</option>
   <option value="OPT5">Option 5</option>
</select>

I tried to use this Java codes to choose Option 2

WebDriverWait wait = new WebDriverWait(driver, 100);

wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".form-row.print-avoid-page-break>label")));

//Start to find the element. The ID is dynamically randomly generated by the system each time the page loads except the last part TaskID, thus looking for the string TaskID   
Select dropdown = new Select (driver.findElement(By.xpath(".//*[contains(@id,'TaskId')]"))); 

dropdown.selectByValue("OPT2");

Selenium returns error

org.openqa.selenium.ElementNotVisibleException: element not visible: Element is not currently visible and may not be manipulated

I have a feeling that this is caused by <div class="subhidden">, but I am not too sure. Any suggestion is highly appreciated. Thanks.

Upvotes: 3

Views: 6919

Answers (4)

Mazik  Pavlovsky
Mazik Pavlovsky

Reputation: 9

To Click an unvisible element try to use Actions. First click - to open dropdown list. Next - Move cursor to element's coordinates, and click at coordinates.

Actions build = new Actions(driver);
By YourSelectItem = By.XPath("xPath to find");
By YourOptionToClick= By.XPath("xPath to find");
IWebElement el  =  driver.FindElement(YourSelectItem));
IWebElement el  =  driver.FindElement(YourOptionToClick));
build.MoveToElement(el).Click().MoveToElement(YourOptionToClick).Click().Build().Perform();

Sorry for C#, I cannot write java analog :)

Upvotes: 1

keylogger
keylogger

Reputation: 872

Found the root cause. My feeling was correct. It is caused by <div class="subhidden"> Because it is a hidden element, Selenium cannot touch it. (Not sure if there is any workaround to deal with hidden element though).

The webpage has 2 layers. Layer 1 is the visible drop-down box where the end user can choose the value.

The HTML code for this layer 1 looks like

    <!-- language: lang-html -->
<input id="Schedule-00-Row831efe50-8f53-4c0f-b9b0-9b622221c62cE-TaskId-Display" class="ui-autocomplete-display validate widget" type="text" autocomplete="off">
    <div class="ui-calendar">
    <ul class="ui-autocomplete-list hidden" style="opacity: 0; visibility: hidden; top: 347px; left: 213px;">
    <li class="visible " data-value=""></li>
    <li class="visible" data-value="OPT1">Option 1</li>
    <li class="visible" data-value="OPT2">Option 2</li>
    <li class="visible" data-value="OPT3">Option 3</li>
    <li class="visible" data-value="OPT4">Option 4</li>
    <li class="visible" data-value="OPT5">Option 5</li>

There is another layer at the back , looks like this

<!-- language: lang-html -->
<span class="ui-autocomplete-display-icon"></span>
<div class="subhidden">
<select id="Schedule-00-Row831efe50-8f53-4c0f-b9b0-9b622221c62cE-TaskId" class="validate widget " data-default-value="" tabindex="5000" data-display-id="Schedule-00-Row831efe50-8f53-4c0f-b9b0-9b622221c62cE-TaskId-Display">
<option value=""></option>
<option value="OPT1">Option 1</option>
<option value="OPT2">Option 2</option>
<option value="OPT3">Option 3</option>
<option value="OPT4">Option 4</option>
<option value="OPT5">Option 5</option>
</select>

So the user will choose the value from drop-down box in layer 1 and then the chosen value will be transferred to drop-down box layer 2 for further processing.

I was trying to code Selenium to select the value from drop-down box in layer 2 (which is hidden) without realizing that there is another layer that can be clicked.

After knowing the root cause, the Selenium code would be simply like this

<!-- language: lang-java -->
WebElement Box = driver.findElement(By.xpath(".//*[contains(@id,'TaskId-Display')]"));
Box.click();

WebElement List = driver.findElement(By.xpath("html/body/ul[1]/li[2]"));
DivisionList.click();

In summary, I was forcing Selenium to select a value from the hidden drop-down list.

@Saifur, Thanks heaps for the discussion.

Upvotes: 0

Saifur
Saifur

Reputation: 16201

Tested code block below and looks fine. Looking at the html it's a fair assumption that the selector does not uniquely return the intendet element. I believe you want the Select tag with containing id TaskId. Just simply do a tag dependent search possibly with //select[contains(@id,'TaskId')] since <input id="Schedule-00-Row136153aa-9fa8-499b-8458-2b155443223bE-TaskId-Display" also has id with same text TaskIdand going forward I suggest you to test the xpath before plug that into test, at least saying from my experience.

WebDriverWait wait = new WebDriverWait(driver, 100);
By selectElementSelector = By.xpath("//select[contains(@id,'TaskId')]");
WebElement selectElement = wait.until(ExpectedConditions.presenceOfElementLocated(selectElementSelector));
Select dropdown = new Select (selectElement);
dropdown.selectByValue("OPT2");

Edit

Another possible option can be finding the element along with the options with a proper selector. Again, you must test the selector to make sure it's unique and it is what you want.

WebDriverWait wait = new WebDriverWait(driver, 100);
String optionToSelect = "OPT1";
//Selector is the trick here
By selectElementSelector = By.cssSelector("select[id*='TaskId']>option[value='" + optionToSelect + "']");

wait.until(ExpectedConditions.presenceOfElementLocated(selectElementSelector)).click();

Upvotes: 4

ratsstack
ratsstack

Reputation: 1021

My 2c worth on this ...

I chucked above HTML into a file, saved as html and opened in FF. I then used the Selenium IDE to record the drop down selection. Once converted to Java I got this:

 new Select(driver.findElement(By.id("Schedule-00-Row136153aa-9fa8-499b-8458-2b155443223bE-TaskId"))).selectByVisibleText("Option 2");

I tested this and it worked fine.

Upvotes: 0

Related Questions