How to avoid Compound Class name error in Page Object?
Asked Answered
S

5

11

When I try to use the class name that having space class = "country name" in page object, I'm getting:

Compound class names not permitted Selenium::WebDriver::Error::UnknownError)

How can I use the class name that having space.

Eg:

class = "country name"
Selfjustifying answered 23/7, 2013 at 11:11 Comment(2)
Possible duplicate of Compound class names are not supported error in WebDriverSilverstein
@Selfjustifying you should probably accept an answer.Unshakable
B
18

Use a CSS selector instead:

.country.name

The important thing to note is that this example is wrong! If "country name" is meant as a name of a country, that is. Class names can't have spaces in them. In fact, the class attribute is a space-separated list of classes. That means that if you have a class country name, it's not one class, it's two different classes your element belongs to - the first is country, the second is name!

Therefore, fix your classes, if they're wrong. If they're not, use a CSS selector, it's the only reliable way to match multiple classes (apart from a very long and complicated XPath expression). Don't use trivial XPath expressions or CSS selectors with naive attribute comparison (//*[@class='country name'] or *[class='country name']), that's just plain wrong.

Baghdad answered 23/7, 2013 at 12:44 Comment(1)
Do we have to escape the slashes and quotations? I'm in Python by the way.Nigrosine
G
3

You can use with this

By.cssSelector("*[class^='classname']");

^ is for if you entering beginning of the class name, 
$ is for if you entering ending of the class name usage example below with sample class name: tech random corner text_left

By.cssSelector("*[class^='tech']");
By.cssSelector("*[class$='text_left']");
Geesey answered 15/12, 2014 at 13:16 Comment(0)
T
2

You can use one of these class names, for example

:class => 'country' 

or

:class => 'name'

if it can't help you then you should switch to use other type of selector :css or :xpath

But note that in case of :css you write:

:css => '.country.name'

and in case of :xpath:

:xpath => '//div[@class='country code']

both should work

Twowheeler answered 3/2, 2014 at 10:35 Comment(0)
B
0

If you have class names which have spaces in them you will get this error. One way of avoiding is creating an xpath for identifying the element. If you show the html I can create the xpath. Also try using class names as multiple objects will have the same class name.

Bister answered 23/7, 2013 at 11:26 Comment(3)
Using XPath (//*[@class='country name'] or even worse //*[contains(@class, 'country') and contains(@class, 'name')]) is very wrong. It treats the class attr as a text while we know it's a space-separated list of tokens and we have the tools to interact with it cleverly (via CSS selectors). What happens if the element gets a new class in addition to the existing classes? What happens if the classes get dynamically swapped? Whenever we can treat data logically instead of stupidly, we should. The only exception is when we are really sure we want to match against text and not logical classesHorrific
Anyway, if you really want to use XPath expressions to match classes, the equivalent to CSS selectors is this: //*[contains(concat(' ',normalize-space(@class),' '),' country ') and contains(concat(' ',normalize-space(@class),' '),' name ')]. Pretty long and complex, eh? This treats the class list as a logical list and not as a dumb text.Horrific
Well my only concern is if there are multiple objects with the same class name. If html is provided I can create a simple xpath which probably might not even require us to use the class name, logicallyBister
R
0

You will have to either remove the space from the class name, in which case Selenium should still in theory find the elements you need or, use a CSS selector and combine it with a period/full stop to concatenate the class names together.

i.e, using a CSS selector to target this:

<div class="country code"></div>

You could use:

div.country.code

or you could make your selector a bit more elaborate:

div[class='country code']
Remonaremonetize answered 23/7, 2013 at 12:22 Comment(1)
div.country.code is the correct solution (can be even without the div part). I'd vote against [class='country code'] any time a day. This treats the class attribute as a simple text while we know it's a space-separated list of tokens and we have the tools to interact with it in a clever way. What happens if the element gets a new class in addition to the existing classes? What happens if the classes get dynamically swapped? In both cases, the naive [class='country code'] solution fails to match while something like .country.code or *[class~=country][class~=code] will work.Horrific

© 2022 - 2024 — McMap. All rights reserved.