Find div element by multiple class names?
Solution 1:
I don't think barak manos's answer has fully explained it.
Imagine we have few elements as the followings:
<div class="value test"></div>
<div class="value test "></div>
<div class="first value test last"></div>
<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
andtest
)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"));
Solution 2:
Try this:
test = driver.findElement(By.xpath("//div[@class='value test']"));
Solution 3:
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
andtest
are mandatory to identify the element, you can use css-selectors as follows:@FindBy(css = ".value.test") @CacheLookup private WebElement test;
-
As an alternative you can also use xpath as follows:
@FindBy(xpath = "//*[@class='value test']") @CacheLookup private WebElement test;
tl; dr
Invalid selector: Compound class names not permitted error using Selenium