0

I have a dropdown list in my menu and I'm trying to select one of two options available after clicking the dropdown. I can't get the options to show though and therefore I'm unable to click either one. This is the source code of the dropdown list on the page:

<span class="ribbondropdown combined importantribbonbutton">
<div class="button_ribbon hasimage ">
<div id="ribbon_nav_dashboard_dropper" class="button_ribbon_dropper ">
<div class="inner"></div>

<div class="button_ribbon_dropdownsection" style="left: 1520px; top: 40px; display: block;">
<table class="dropdownlist" width="100%" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="icon"></td>
<td class="value">Option 1</td>
</tr>
<tr>
<td class="icon"></td>
<td class="value">Option 2</td>
</tr>
</tbody>
</table>
</div>
</div>
</span>

The first four lines are the area I want to click. the rest of the code is for the section that becomes visible after clicking and here I'd like to click 'Option 2'.

I'm currenlty using the following:

driver.findElement(By.id("ribbon_nav_dashboard_dropper")).click();
driver.findElement(By.xpath("//div[@class='value' and text()='Option 2']")).click();

this however results in a failure:

org.openqa.selenium.ElementNotVisibleException: Element is not currently visible and so may not be interacted with

If I comment out the second line, only clicking on the dropdown to show the options and make the test show the options it does not show. If I do this manually I do get the two options. I've looked at another question with the same exception but the proposed solution did not work for me: Java webdriver: Element not visible exception

7
  • I just noticed that when I look at the code in Firebug the section containing <div class="button_ribbon_dropdownsection" is greyed out when the options are not showing, if I then click on the icon for the dropdown menu or the arrow to its right the code 'comes to life' and display changes from none to block. If it has not been clicked at all the entire section containing style="left: 1520px; top: 40px; display: block is not present Commented Oct 15, 2015 at 16:33
  • 1
    Are are getting exception on the first line? driver.findElement(By.id("ribbon_nav_dashboard_dropper")).click(); Commented Oct 15, 2015 at 16:48
  • 1
    What about an implicit wait for the second element? Commented Oct 15, 2015 at 17:02
  • @Striker, I'm getting the exception at the second line, the first line passes without a problem Commented Oct 16, 2015 at 7:54
  • @SiKing, I tried implicitly waiting with the following code but that didn't work (driver.manage().timeouts().implicitlyWait(4, TimeUnit.SECONDS);). Also tried waiting for the element to be visible but that too did not work (new WebDriverWait(driver, 30).until(ExpectedConditions.visibilityOfElementLocated(By.xpath) Commented Oct 16, 2015 at 7:56

3 Answers 3

0

Have you tried scrolling the element to the visible range before firing the action on to it. If the element is out of the visible area selenium cannot fire actions upon it.

WebElement webelement = driver.findElement(By.xpath("//div[@class='value' and text()='Option 2']"))
JavascriptExecutor jsExecutor = (JavascriptExecutor) driver;
jsExecutor.executeScript("arguments[0].scrollIntoView(false);", webElement);
webElement.click();
Sign up to request clarification or add additional context in comments.

3 Comments

I tried getting the element in the visible range by clicking on the button (driver.findElement(By.id("ribbon_nav_dashboard_dropper")).click();) but that does not make it visible for some reason. I tried your code this just now but get a failure (NoSuchElementException) on the first line.
As per your code in the question you have to click on the expand button before clicking on the option. driver.findElement(By.id("ribbon_nav_dashboard_dropper")).click(); then try the code which i have shared earlier
I tried that but that did not change the style of the element that was needed to show the code for the options. See my answer, that now works. Thank you
0

It turned out the option I was trying to click in the dropdown menu was in a section of code that was not available. I am unsure why an automated click did not change the style of a given element but this is required for the options to show. I automatically changed the style of the element with the following:

JavascriptExecutor js = (JavascriptExecutor) driver;
WebElement element = driver.findElement(By.xpath("//div[@class='dropdownsection']"));
js.executeScript("arguments[0].setAttribute('style', 'left: 1520px; top: 40px; display: block;')",element);

Now that the Style is changed the section of code containing the options available is active showing my options and I can now click my prefered option:

driver.findElement(By.xpath("//*[@class='value' and text()='Option 2']")).click();

Comments

0

I will start by telling you that I am learning html formatting and syntax so you may find that I'm taking the long-way around a problem. I tried creating a basic webpage locally based on your sample and I was not able to create the drop-down for any validation of this proposal.

That being said...

"If I comment out the second line, only clicking on the dropdown to show the options and make the test show the options it does not show."

Focus on this first. If you can't get the element to show, then you will never be able to click on it.

Based on the described behavior, I think your combo id lookup is perhaps the wrong element in the structure.

By.id("ribbon_nav_dashboard_dropper")

The Junit class below is basically how I would go about testing if I've got the right element for the drop down. Fill in the String arrays in the buildLookups method and the test cases should tell you which of the options you've entered will allow the 'option[2]' to be clicked.

I also took a crack at implementing how the performValidation method would work in this case, but I'd recommend double checking that just to be sure I've understood the problem correctly.

package stackoverflow.proof.selenium;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * Parameterized test which can be used to validate lookups for a single well-defined desired interaction in Selenium.
 * 
 */
@RunWith(Parameterized.class)
public class SeleniumLookupValidationUtil {
    /** Test URL where the element should be validated.*/
    private static final String TEST_URL = "myURL";
    /** Function which converts a String into a {@link By#id(String)} reference.*/
    private static final Function<String, By> AS_ID_LOOKUP = new Function<String, By>() {
        @Override
        public By apply(String arg0) {
            System.out.println("Id Lookup: " + arg0);
            return By.id(arg0);
        }
    };
    /** Function which converts a String into a {@link By#xpath(String)} reference.*/
    private static final Function<String, By> AS_XPATH_LOOKUP = new Function<String, By>() {
        @Override
        public By apply(String arg0) {
            System.out.println("xpath Lookup: " + arg0);
            return By.xpath(arg0);
        }
    };
    /** Function which converts a String into a {@link By#cssSelector(String)} reference.*/
    private static final Function<String, By> AS_CSS_SELECTOR_LOOKUP = new Function<String, By>() {
        @Override
        public By apply(String arg0) {
            System.out.println("css Lookup: " + arg0);
            return By.cssSelector(arg0);
        }
    };
    /** Function which converts a String into a {@link By#className(String)} reference.*/
    private static final Function<String, By> AS_CLASS_NAME_LOOKUP = new Function<String, By>() {
        @Override
        public By apply(String arg0) {
            System.out.println("className Lookup: " + arg0);
            return By.className(arg0);
        }
    };
    /** Function which converts a String into a {@link By#linkText(String)} reference.*/
    private static final Function<String, By> AS_LINK_TEXT_LOOKUP = new Function<String, By>() {
        @Override
        public By apply(String arg0) {
            System.out.println("LinkText Lookup: " + arg0);
            return By.linkText(arg0);
        }
    };

    /**
     * Creates the data for running the test instance.
     * @return Collection of Object arrays.  Each array in the collection represents a different test execution.
     */
    @Parameters(name="{0}")
    public static Collection<Object[]> buildLookups() {
        //TODO:  Fill in add as many possible lookups for the drop-down element as you can find.
        String[] ids = new String[]{"id1", "id2"};
        String[] xpaths = new String[]{};
        String[] cssSelectors = new String[]{};
        String[] classNames = new String[]{"A", "B"};
        String[] linkTexts = new String[]{};

        //I use the map so I can loop through the dataset later.
        Map<Function<String, By>, String[]> associations = Maps.newHashMap();
        associations.put(AS_ID_LOOKUP, ids);
        associations.put(AS_XPATH_LOOKUP,xpaths);
        associations.put(AS_CSS_SELECTOR_LOOKUP, cssSelectors);
        associations.put(AS_CLASS_NAME_LOOKUP, classNames);
        associations.put(AS_LINK_TEXT_LOOKUP, linkTexts);

        List<Object[]> parameters = Lists.newArrayList();
        for (Function<String, By> converter: associations.keySet()) {
            String[] lookupStrings = associations.get(converter);
            for (String lookup : lookupStrings) {
                By by = converter.apply(lookup);
                parameters.add(new Object[]{by});
            }
        }

        return parameters;
    }

    /** The By lookup to use for the current test validation.*/
    private final By target;
    /** WebDriver for testing.*/
    private WebDriver driver;

    /**
     * Test constructor.
     * @param lookup By to be used for this validation.
     */
    public SeleniumLookupValidationUtil(By lookup) {
        this.target = lookup;
    }

    /**
     * Creates the webdriver and establishes our validation state.
     */
    @Before
    public void initWebDriver() {
        driver = new FirefoxDriver();
        driver.get(TEST_URL);
        //TODO:  Any other setup to make the test case valid.
    }

    /**
     * Performs the thing we actually want to know about.
     */
    @Test
    public void performValidation() {
        WebDriverWait wait = new WebDriverWait(driver, 30);
        wait.until(ExpectedConditions.elementToBeClickable(target));
        WebElement option2 = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//div[@class='value' and text()='Option 2']")));
        option2.click();
    }

    /**
     * Closes all test browser windows and destroys the driver reference.
     */
    @After
    public void destroyWebDriver() {
        for (String window : driver.getWindowHandles()) {
            driver.switchTo().window(window);
            driver.close();
        }
    }
}

I use the google.guava api quite a bit, you will need that library to run this code. Here is the maven pom dependency I use for that reference:

 <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>LATEST</version>
      <scope>compile</scope>
    </dependency>

Best of Luck.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.