Find div element by multiple class names?
Asked Answered
A

4

80

<div class="value test" /> I'd like to identify that web element. It only has this two classes defined. I cannot do the following as className does not take a space separated value. What are alternatives?

@FindBy(className = "value test")
@CacheLookup
private WebElement test;
Aright answered 11/2, 2014 at 21:21 Comment(0)
P
189

I don't think barak manos's answer has fully explained it.

Imagine we have few elements as the followings:

  1. <div class="value test"></div>
  2. <div class="value test "></div>
  3. <div class="first value test last"></div>
  4. <div class="test value"></div>

How XPath matches

  • Match only 1 (exact match), barak's answer

    driver.findElement(By.xpath("//div[@class='value test']"));
    
  • Match 1, 2 and 3 (match class contains value test, class order matters)

    driver.findElement(By.xpath("//div[contains(@class, 'value test')]"));
    
  • Match 1, 2, 3 and 4 (as long as elements have class value and test)

    driver.findElement(By.xpath("//div[contains(@class, 'value') and contains(@class, 'test')]"));
    

Also, in cases like this, Css Selector is always in favor of XPath (fast, concise, native).

  • Match 1

    driver.findElement(By.cssSelector("div[class='value test']"));
    
  • Match 1, 2 and 3

    driver.findElement(By.cssSelector("div[class*='value test']"));
    
  • Match 1, 2, 3 and 4

    driver.findElement(By.cssSelector("div.value.test"));
    
Pennon answered 11/2, 2014 at 22:0 Comment(1)
thanks for the nice explanations, it works perfectly in my selenium instanceForgave
R
16

Try this:

test = driver.findElement(By.xpath("//div[@class='value test']"));
Rootlet answered 11/2, 2014 at 21:25 Comment(0)
G
6

If anyone still wonders, i accomplished this by connecting the class names with dots:

Python:

time_element = post.find_elements(By.CLASS_NAME, 'MUxGbd.wuQ4Ob.WZ8Tjf')[0].text
Ginkgo answered 13/11, 2022 at 14:13 Comment(0)
T
2

Class By.ByClassName

Class By.ByClassName is defined in By.java as follows:

/**
 * Find elements based on the value of the "class" attribute. If an element has multiple classes, then
 * this will match against each of them. For example, if the value is "one two onone", then the
 * class names "one" and "two" will match.
 *
 * @param className The value of the "class" attribute to search for.
 * @return A By which locates elements by the value of the "class" attribute.
 */
public static By className(String className) {
  return new ByClassName(className);
}

This usecase

So as per the defination you can't pass multiple classes i.e. value and test as arguments to @FindBy(className = "..."). Sending multiple classes will raise an error as:

invalid selector: Compound class names not permitted

Solution

There are multiple approaches to solve this usecase as follows:

  • If the element is uniquely identified only through the classname value you can use:

    @FindBy(className = "value")
    @CacheLookup
    private WebElement test;
    
  • If the element is uniquely identified only through the classname test you can use:

    @FindBy(className = "test")
    @CacheLookup
    private WebElement test;
    
  • If both the classnames, value and test are mandatory to identify the element, you can use as follows:

    @FindBy(css  = ".value.test")
    @CacheLookup
    private WebElement test;
    
  • As an alternative you can also use as follows:

    @FindBy(xpath   = "//*[@class='value test']")
    @CacheLookup
    private WebElement test;
    

tl; dr

Invalid selector: Compound class names not permitted error using Selenium

Tinned answered 3/3, 2020 at 21:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.