Selenium CSS selector by id AND multiple classes - css-selectors

Using selenium for the first time here, I was wondering why:
final WebElement justAnId = findElement(By.cssSelector("#someId"));
final WebElement whatIWant = justAnId.findElement(
By.cssSelector(".aClass.andAnother input[type=text]")
);
works, but not:
final WebElement whatIWant = findElement(By.cssSelector(
"div#someId.aClass.andAnother input[type=text]"
));
Although they seem equivalent to me I get:
org.openqa.selenium.NoSuchElementException: Unable to locate element:
{"method":"css selector","selector":"div#someId.aClass.andAnother input[type=text]"}
Is this intended behaviour or a bug in Selenium? I had a quick look in the bug tracker in Selenium but I didn't see anything about that. I wanted to ask here before raising an issue that doesn't need to be. Also as far as I understand it doesn't work in IE6 but who cares. I was using firefox for this run.

Actually the two are quite different selectors.
Here is your cssSelector:
div#someId.aClass.andAnother input[type=text]
But what you really wanted to write was:
div#someId .aClass.andAnother input[type=text]
notice the space between ID and class. you need that.

findElement() finds an element in the current context, which means your first snippet of code is really finding an element that matches .aClass.andAnother input[type=text], which is contained within #someId. The element with that ID may or may not contain the two classes; WebDriver doesn't assume you're referring to the same element; it just finds the input as long as its ancestors are #someId and .aClass.andAnother.
This is completely different from div#someId.aClass.andAnother input[type=text], which finds any input[type=text] within div#someId.aClass.andAnother only (i.e. it's a div that contains both the ID and the classes).

Related

How to iterate over elements in selenium

Actually i want to read emails one by one in junk folder of "outlook:live" and mark emails "Not spam".
emails = WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.XPATH,"//div[#class = 'xoCOIP8PzdTVy0T6q_uG6']")))
This xpath matches 400 instances. I want to make a loop to select one email at a time like select first email, click on the div and perform action and then 2nd email and so on. I'm trying this
emails = WebDriverWait(driver,
5).until(EC.element_to_be_clickable((By.XPATH,"//div[#class =
'xoCOIP8PzdTVy0T6q_uG6']")))
for count in range(0,len(emails)):
(emails)[count+1].click()
Please help me know where im doing wrong. Thanks in advance
It appears that the function you're using to return the clickable elements is only returning a single element, so you'll have to use a different function, make a change in your logic, etc.
For instance, you could use Selenium's find_elements_by_xpath("//div[#class = 'xoCOIP8PzdTVy0T6q_uG6']") which will return a list of WebElement object(s) if the element(s) are found, or an empty list if the element(s) is not found. This will, of course, not take into consideration the possibility of the elements not being completely loaded on the page. In my experience, just slapping a time.sleep(10) after you open the page is "'good enough".
I recommend making sure your elements can be discovered and interacted with first to make sure this isn't all in vain, if you haven't already.
Another option is to add another function, something like a elements_to_be_clickable() function, to the Expected Conditions source code.
From the Expected Condition documentation, I've done some research and it looks like the element_to_be_clickable() function only returns a single element. Moreover, from the source code, said function mainly makes use of the visibility_of_element_located() function. I believe you could follow similar logic to the element_to_be_clickable() function, but instead use the visibility_of_all_elements_located() function, in order to return multiple WebElements (since visibiilty_of_all_elements_located() returns a list of WebElements).

isEnable() is not working in selenium webdriver for find the button is enabled or disabled?

i am trying the bellow code,but always return true value.
if(updatebuton_status=="true"){
Thread.sleep(timmer*3);
//click on the update button
//ieDriver.findElement(By.xpath("html/body/div[1]/div/div/div/div[3]/div/div[1]/div/div/table/tbody/tr/td/table/tbody/tr/td[3]/div/div/div[2]/div[3]/div/div/div/div[2]/div/div[2]/div[2]/div/div/div[3]/div[2]/div/div/div/div[3]/div/div/div/div/div/div[2]/div[1]/div/div/div/div/table[1]/tbody/tr/td/table/tbody/tr/td[3]/span/table/tbody/tr[2]/td[2]")).click();
ieDriver.findElement(By.xpath("/html/body/div[1]/div/div/div/div[3]/div/div[1]/div/div/table/tbody/tr/td/table/tbody/tr/td[3]/div/div/div[2]/div[3]/div/div/div/div[2]/div/div[2]/div[2]/div/div/div[3]/div[2]/div/div/div/div[3]/div/div/div/div/div/div[2]/div[1]/div/div/div/div/table[1]/tbody/tr/td/table/tbody/tr/td[1]/span/table/tbody/tr[2]/td[2]")).click();
}else{
Thread.sleep(timmer*3);
//click on the Add button
ieDriver.findElement(By.xpath("/html/body/div[1]/div/div/div/div[3]/div/div[1]/div/div/table/tbody/tr/td/table/tbody/tr/td[3]/div/div/div[2]/div[3]/div/div/div/div[2]/div/div[2]/div[2]/div/div/div[3]/div[2]/div/div/div/div[3]/div/div/div/div/div/div[2]/div[1]/div/div/div/div/table[1]/tbody/tr/td/table/tbody/tr/td[1]/span/table/tbody/tr[2]/td[2]")).click();
}
I think somewhere you are doing wrong as your xpath is too long recommended to use relative xpath. and if your element having id then use it directly
I don't know how you are checking that element is displayed
use following method to do same -
boolean check= driver.findElement(By.id("tVLQur-btn")).isEnabled();
if(check) // if `check` returns true then go in if condition
{
driver.findElement(By.id("tVLQur-btn")).click();
}
else
{
// DO SOME OTHER FUNCTIONALITY
}
Edited
If your button id is dynamic then use following xpath to find the element
//td[contains(.,'Update')]/../preceding-sibling::tr//button
like
boolean check= driver.findElement(By.xpath("//td[contains(.,'Update')]/../preceding-sibling::tr//button")).isEnabled();
It will find your update button and check weather it is enable or not
I believe at the very least if you break the line into two statements, one to located the element, and the next to check its enabled status, at least you'll know that the problem (most likely) lies in the element location, as it would return a nul to the web element and isEnabled would return a null pointer exception. There are always ways to use relatively short xpaths if no consistent ID is available. Check your browser for add-ins that include the word xpath, and you'll see there are a variety of xpath helpers out there. The inspect element option is the safest, at least in theory, but it's not always the best.

Unable to find and element in selenium using name

I am not able to fine the element by name.
The code is simple I have mentioned below
WebElement FirstName = driver.findElement(By.name("anyname"));
FirstName.sendKeys("xyz");
I get the following error
Unable to find element with name == txtVFNAME (WARNING: The server did
not provide any stacktrace information) Command duration or timeout:
282 milliseconds
Is there a way to locate the element by DOM?
Also can I use some sort of loop which will help me in the visibility if this element?
Your question is clear but the data your provided is not enough to help. I believe the element you are looking is might be in iframe or hidden. Please provide the source code of the webpage you testing.
You can find all needed elements using findElements
List<WebElement> inputs = driver.findElements(By.xpath("//*[#name='Your_name']"));
for (var element=0; element < inputs.size(); element ++){
if( inputs[element].isDisplayed()){
//your code
}
}
In this case //*[#name='Your_name'] you are searching on attribute name. For more xpath cases take a look on cheat sheet
Is there a way to locate the element by DOM?
Open a Firefox browser. Launch the URL and Firebug. There should be search box where you can search for "txtVFNAME".

Selenium ElementNotFoundException when the element in a loop

Am writing the selenium code for an element. It gives the error as ElementNotFoundException
I know the reason that the element was hidden or its style is none.
I Googled and I found the following solution:
((JavascriptExecutor) this.webdriver).executeScript("arguments[0].click();", elementToClick);
…but my element in a loop. For the first iteration it is successful but in the further iterations it is throwing the same exception.
Can anyone explain the arguments[0]?
Yes, in your example, "arguments[0]" = elementToClick . Also, I only use a JavascriptExecutor when I have no other options to click something, and that almost never happens. For example, I use JavascriptExecutor to do page-downs because Selenium doesn't have a feature that does that properly.
So, if the element you are seeking really does have a 'display=none' set on it, what you should do instead is use an ExpectedConditions.visibilityOfElementLocated condition with a WebDriverWait (or a FluentWait).
For all other cases of elements which are visible or not visible at times, use ExpectedConditions.presenceOfElementLocated.
Using the Wait classes with ExpectedConditions, you can use a while loop to ignore certain exceptions and do re-tries until the condition is satisfied.

How to declare, same webelement with different ids using Findby?

For instance, is it possible to define:
#FindBy(By.id("id1") OR By.id("form1:id1"))
public WebElement button
So that button having either "id1" or "form1:id1" should work fine?
You can use the #FindBys annotation, the syntax is:
#FindBys({#FindBy(id = "foo"),
#FindBy(className = "bar")})
The JavaDoc describes it here:
http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/FindBys.html
Well,
use whathever you want, as long as it works
Personally I would use #FindBy(By.id("id1")) but it is just point of choice.
Also, there is no value added in referring same element twice with two different methods. It will only cause mess in your code
EDIT
As I understood your comment, there is element on the page which constantly changes its ID. If you need to refer to such elements, try using xPath See for example this xpath tutorial
The idea is that you will point to some place in the DOM rather than to specific ID
Use Xpath or CSS selector to do that. Or Java to store the ID name in String and then you can fill it to your Id.

Resources