How to identify elements classname containing special characters using Selenium and VBA - vba

I'm trying to learn more about how Selenium works with VBA and I'm trying to do somethings about the trendings behaviors of ecommerce nowadays.
In this case, I don't know how works the FindelementByclass when it has special characters like _ or - inside, because it always gives me empty result and I need to identify it because I want to go through every class called as it.
<span class="minificha__sku ng-binding">Cód TG: AS0-322</span>

space in class means it has two classes,
class="minificha__sku ng-binding"
means it has "minificha__sku" and "ng-binding" , so use xpath or css instead of byclass or use either of the two class not two
css:
span[class="minificha__sku ng-binding"]
xpath
//span[#class="minificha__sku ng-binding"]

To identify the element you can use either of the following Locator Strategies:
Using FindElementByClassName I:
bot.FindElementByClassName("minificha__sku")
Using FindElementByClassName II:
bot.FindElementByClassName("ng-binding")
Using FindElementByCss:
bot.FindElementByCss("span.minificha__sku.ng-binding")
Using FindElementByXPath:
bot.FindElementByXPath("//span[#class='minificha__sku ng-binding']")

Related

Problems extracting elements by class names with Selenium

From this page: https://www.realestate.com.kh/buy/, which looks like this in the inspector:
I'm trying to extract all elements of class css-1uuzwjq eq4or9x0 into a list in order to click on the elements and further explore.
I have this code, in which I try to get the elements by their Xpath:
ads = browser.find_elements_by_class_name('css-1uuzwjq eq4or9x0')
for ad in ads:
ad.click()
However, the list always ends up empty. What am I doing wrong?
class attribute holds multiple classes , each class is separated by space. In your case, 'css-1uuzwjq eq4or9x0' are two classes not one
you can find it as :#
xpath
in xpath it validates the class attribute value is exactly the same
//*[#class="css-1uuzwjq eq4or9x0"]
CSS
in css it checks for element that contains both the mentioned class, each class should be mentionedwith a dot
.css-1uuzwjq.eq4or9x0
if you want exact match , use the below locator as it checks the class attribute value to be exact
[class="css-1uuzwjq eq4or9x0"]
using class locator
browser.find_elements_by_class_name('css-1uuzwjq.eq4or9x0')
calss locator uses css locator under the hood , so when you pass a class name, it just adds 'dot' in front of it . so to make it a valid locator pass all classes by replacing space with dot
//div[#class='list']/div[./header[contains(#class,'featured')]]
I would use this xpath to obtain all the divs needed to search.
use /div/header/a if you want the a tag to click.
So it would be
driver.get('https://www.realestate.com.kh/buy/')
hrefs=[x.get_attribute('href') for x in driver.find_elements(By.XPATH,"//div[#class='list']/div/header/a")]
print(hrefs)
for href in hrefs:
driver.get(href)
Would retrieve all the hrefs to loop and will prevent using driver.back() and all the stale elements you will get.
I would not recommend getting by class name because they seem dynamic also those are multiple class names which are grabbed by a css selector.
css-1uuzwjq eq4or9x0 -> .css-1uuzwjq.eq4or9x0

How to find webelement using style property

Below is the HTML code of an element and I want to locate this element by classs and style property using selenium webDriver in java
<div class="qooxdoo-table-cell" style="left:252px;width:117px;height:24px;"/>
suggest a way which can be help full in selenium
I want to locate the element using java code
i.e. Driver.findelement(by. ....
As long as the element isn't unique you must grab both attributes:
This is the general form, replacing the empty strings for your required class and style:
driver.findElement("By.xpath(//div[#class='' and style='']");
So:
driver.findElement(By.xpath("//div[#class='qooxdoo-table-cell' and style='left:252px;width:117px;height:24px;']");
Best of luck!
If you need to match <div> with exact style attribute, you can try something like
driver.findElement(By.xpath("//div[#class='qooxdoo-table-cell'][#style='left:252px;width:117px;height:24px;']"))
Another way is to use cssSelector as follows:
driver.findElement(By.cssSelector("div[style='left:252px;width:117px;height:24px;']"));
If you are using a older version of selenium you can as well use the older version of cssSelector.
driver.find_elements_by_css_selector("div[style='left:252px;width:117px;height:24px;']")
Note: this function still works in current version of Selenium (with DeprecationWarning )

How to find exact value using xpath in selenium webdriver?

I am using XPath to find exact value:
//h5[#class='familyName productFamilyName'][contains(text(),'Dozers ')]
but it was failing because in my application there are 2 elements with text values "Dozers " and "Dozers wheel" which is come under same class.
I can't use id locators,because it is dynamically generating in my application like //div[#id="482"]/div/div[1]/h5.
Please suggest me any solution.
If you want to match element with exact innerHTML value just use
//h5[#class='familyName productFamilyName'][text()='Dozers')]
or
//h5[#class='familyName productFamilyName'][text()='Dozers wheel')]
Depending on HTML structure you might need to use [.='Dozers'] or
[normalize-space(.)='Dozers'] instead of [text()='Dozers']

XPath query search

Such structure is given
<div class="user-number">123</div>
<div class="user-state">
<span class="u-state-icon icon icon-1"></span>
<span> User1</span>
</div>
I've tried such (incorrect) xpath for locating User1 by user-number and do not understand where is the problem..
xpath=//*[#class='user-number' and text() = '123']/following-sibling::*[contains(#class,'user-state')]/descendant::*[contains(#text,'User1')]
What is the best way to debug it?
For example, if
xpath=//*[#class='user-number' and text() = '123']/following-sibling::*[contains(#class,'user-state')]
locates some element - how to print out its text property - to check which element is actually located?
Your xpath expression is, surely, incorrect - #text should be replaced with text() (or just .):
//*[#class='user-number' and . = '123']/following-sibling::*[contains(#class,'user-state')]/descendant::*[contains(.,'User1')]
Debugging xpath expressions is usually done using the browser developer tools: in the firebug, or inside a browser console. For instance, in the google-chrome console, you can execute the following:
$x("//*[#class='user-number' and . = '123']/following-sibling::*[contains(#class,'user-state')")
And see if there is a match.
Or, you can also debug it inside your code. For example (using python), find the first div element and print out it's text:
element = driver.find_element_by_xpath("//*[#class='user-number' and . = '123']")
print(element.text)
The meta-question is, how to debug XPath expressions?
Well, for simple ones like these, it's really best to just stare at them till you see the problem. Check the spelling of names, check namespaces, check whitespace issues. At least it's easier than debugging regular expressions.
For more complex XPaths, try breaking them up. Remove a predicate and see if that makes a difference. Or work in reverse, build up the path expression by adding conditions, checking at each stage that it still finds something.
If you're really seriously into XPath, consider schema-aware processing: this will match your XPath expression against a schema to make sure it makes sense.
Consider using a visual XPath processor for debugging. There are a number around. I use the XPath processor in oXygen (though not really for debugging the XPath, more for discovering the content of the document, but those tasks often need to be done together.)

Selenium RC Having problems with XPath for a table

I'm trying to select an element given by:
/html/body[#id='someid']/form[#id='formid']/div[#id='someid2']/div[#id='']/div[#id='']/div[#id='']/table/tbody[#id='tableid']/tr[7]/td[2]
Now the html of that row I'm trying to select looks like this:
<tr>
<td class="someClass">some text</td>
<td class="someClass2">my required text for verifying</td>
</tr>
I need to check whether my required text for verifying exists in the page.
I used selenium.isTextPresent("my required text for verifying"); and it doesnt work
So now I tried with selenium.isElementPresent("//td[contains(text(),'my required text for verifying')]")
This works sometimes but occassionally gives random failures.
Tried with selenium.isElementPresent(//*[contains(text(),'my required text for verifying')]) too..
How do I verify this text on the page using selenium?
The problem is not with the page taking time to load. I took screenshots before the failure occurs and found that the page was fully loaded so that shouldnt be the problem.
Could someone please suggest any way to select this element or any way to validate this text on the screen?
Try locating it by CSS:
assertText(selenium.getText("css=.someClass2"), "my required text for verifying");
The above should give a better failure message than isElementPresent, but you can still use that with CSS locators:
assertTrue(selenium.isElementPresent("css=.someClass2"));
If there is an issue with the load times you could try waiting for the element to be present:
selenium.waitForCondition("var value = selenium.isElementPresent('css=.someClass2'); value == true", "60000");
Some other XPath locators that might work for you, if you prefer not to use CSS locators:
//td[contains(#class, 'someClass2')
xpath=id('tableid')/tr[7]/td[2]
xpath=id('tableid')/descendant::td[contains(#class, 'someClass2')][7]
I've never heard of selenium; but your initial XPath is unnecessarily fragile and verbose.
If an element has an id, it's unique; using such a long XPath just to select a particular element is unnecessary; just select the last element with the id. Further, I see that you're occasionally selecting xyz[#id=''] - if you're trying to select elements without id attributes, you can do `xyz[not(#id)] instead.
Assuming your initial XPath is basically correct, it would suffice to do something like this:
//tbody[#id='tableid']/tr[7]/td[2]
However, using a specific row and column number like that is asking for trouble if ever anyhow changes details of the html. Also, it's atypical to have id's on tbody elements, perhaps the table element has the id?
Finally, you may be running into space-normalization issues. In xml, multiple consecutive spaces are often considered equivalent to a single space, and you're not accounting for that. In particular, if the xhtml is pretty-printed and contains a line-break in the middle of your sought-after text, it won't work.
//td[contains(normalize-space(text()),'my required text for verifying')]
Finally, text() explicitly selects
child text nodes - so the above xpath won't select elements where the text isn't the immediate child of td (e.g. <td><b>my required text for verifying</b></td>) won't match. Perhaps you mean to look up the concatenated text vale of all descendents:
//td[contains(normalize-space(string(.)),'my required text for verifying')]
Finally, type conversion can be implicit in XPath, so string(.) can be replaced by . in the above, leading to the version:
//td[contains(normalize-space(.),'my required text for verifying')]
This may be slow on large documents since it needs to normalize the spaces and perform a string search for each td element. If you run into perf problems, try to be more specific about which td elements need to be inspected, or, if you don't care where the text occurs, try to reduce the number of "calls" to normalize-space by normalizing the entire doc in one go (e.g. via /*[contains(normalize-space(.),'my required text for verifying')]).