Unable to recognize Element with relative xpath or other locator - selenium

I am facing an issue where I am unable to locate Element on webpage with any type of locator expect Absolute xpath. Here are details:
URL : https://semantic-ui.com/modules/dropdown.html#selection
Required Element Screen shot:
Manually created Xpath Screen shot( Please note that I am able to recognize Element in web application with manually created xpath but Same xpath is not working in selenium code)
But Same xpath is not working in selenium script.
PLEASE NOTE THAT I AM ABLE TO IDENTIFY SAME OBJECT WITH Absolute xpath
Please help to me to understand reason for this.
Here is code:
public static WebDriver driver;
public static void main(String[] args) {
driver= new FirefoxDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("https://semantic-ui.com/modules/dropdown.html");
//Selection
driver.findElement(By.xpath("//div[#class='ui selection dropdown upward']")).click();
driver.findElement(By.xpath("//div[#class='menu transition visible']/div[text()='Female']")).click();
System.out.println("Done");

This may be issue with your first x-path. You may try the following code. It may work.
driver.findElement(By.xpath("//div[#class='ui selection dropdown']").click();
driver.findElement(By.xpath("//div[#class='menu transition visible']/div[text()='Male']").click();

You are missing a preceding wildcard in you driver.FindElement XPath.
Instead of driver.findElement(By.xpath("//div..."));, do driver.findElement(By.xpath("//*div..."));.
Currently, what your code is doing is telling the XPath locator to find a first level div (not easily possible, as the first item is almost always the document body), but the wildcard of "*" tells it that it can look for the div at any level.
As an aside, please edit your answer up top with actual code instead of pictures so others with the same problem can find their solution easier.

Longshot:
You are using Chrome to look at the source, but Selenium is using Firefox.
There is a chance that the source is rendered differently between the two browsers. Specifically, your xpath is relying on an exact match of class. I do know that FireFox is notorious for modifying source output.
I haven't done any testing but I would not be surprised if the class is in a different order and it's failing on an exact match.
There are two solutions if that is the case:
Don't do a single exact match (xpath = "") but instead do a mix of contains joined with && (contains ui && contains selection && dropdown)
Don't rely on the output from the console tab. Instead "View Page Source" and view what is actually being sent instead of what is being interpreted by the browser

Find the dropdown container element firstly, then use it to find self descendant, like option etc.
driver.get("https://semantic-ui.com/modules/dropdown.html");
// find dropdown container element
WebElement dropdownWrapper = driver.findElement(
By.xpath("//div[#class='html']/div[input[#name='gender']]"));
// expand drop down options by click on the container element
dropdownWrapper.click();
// or click the down arrow
dropdownWrapper.findElement(By.css('i')).click();
// select option
dropdownWrapper.findElement(By.xpath(".//div[text()='Female']")).click();

To locate the element with text as Gender and select the option Female you can use the following Locator Strategy :
Code Block :
System.setProperty("webdriver.chrome.driver", "C:\\path\\to\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get("https://semantic-ui.com/modules/dropdown.html#selection");
driver.findElement(By.xpath("//div[#class='another dropdown example']//div[#class='ui dropdown selection']")).click();
driver.findElement(By.xpath("//div[#class='another dropdown example']//div[#class='ui dropdown selection active visible']//div[#class='menu transition visible']//div[#class='item' and contains(.,'Female')]")).click();
System.out.println("Gender Female selected.");
Console Output :
Gender Female selected.

This might be helpful to clearify how selectors are working in general:
.(dot): Dot at starting represents the current node. It tells us that the processing will start from the current node.
. .(double dot): It will select parent of current node. For example, //table/. . will return div element because div is the parent of table element.
‘*’: is used to select all the element nodes descending from the current node. For example:
/table/*: It will select all child elements of a table element.
//*: It will select all elements in the document.
//*[#id = ‘username’]: It will select any element in document which has an attribute named “id” with the specified value “username”.
#: It represents an attribute which selects id, name, className, etc. For example:
#id: It will select all elements that are defined with the id attribute in the document. No matter where it is defined in the document.
//img/#alt: It will select all the img elements that are defined with the #alt attribute.
//td[#*]: It will select all td elements with any attribute.
Here is a link to the article:
https://www.scientecheasy.com/2020/07/selenium-xpath-example.html/

Related

How can I check that a dropdown field is disabled using selenium?

I am trying to write a function in selenium to check if a Reasons dropdown is showing as disabled, but can't quite get the xpath right. The code for the dropdown is in the pic, the function I'm working on is the second one (InputDisabled), having based it on the working first one (SearchDisabled):
` public By SearchDisabled(string searchId) => By.XPath($"//div[#id='{searchId}']//div[contains(#class, 'v-input--is-disabled')]");
public By InputDisabled(string inputId) => By.XPath($"//div[#id='{inputId}']//div[contains(#class, 'v-input--is-disabled')]");`
The inputId going into it is 'ai-confirm-allergy-modal-reason'. I've tried it as 'input[contains...' and 'contains(#disabled, 'disabled'...' among other things, but my xpath knowledge isn't great yet!
dropdown code
Use below code
String value = driver.findElement(By.XPath("//input[contains(#id, 'ai-confirm-allergy')]").getAttribute("disabled");
Assert.AssertEquals(value, "disabled");
I do not quite get your question.
well if you are trying to use xpath to locate an element, you can just use the id; assuming that it is unique.so:
driver.findElement(By.xpath("//input[contains(#id, 'ai-confirm-allergy')]")
should locate the webelement.
However, your xpath for the SearchDisabled is locating a div containing class 'v-input--is-disabled' with in another div with id of '{searchId}';
the same logic goes for the next one. your xpath is trying to locate a div containing class 'v-input--is-disabled' which is located with in another div located using input id. I don't think this combination can locate the element highlighted in the picture.

How to select one from duplicate tag in page in java in selenium webdriver

I am using Selenium WebDriver and I have number of items on a page and each item on page is a separate form type.
I have saved all of these form elements in a list and I am iterating over every item in an attempt to get the name of the element by using the "alt" attribute.
However when I try to get the "name" attribute from the input element it is always returning the first input tag found on that page, not the name attribute of the element I have currently selected.
The syntax I am using is:
((Webdriver imgtags.get(i)).findelement(By.xpath("//input[#name='qty']")).sendKeys ("100");
I have also tried to get the id from the tag by using:
((Webdriver imgtags.get(i)).getAttribute("id");
It's returning a blank value, but it should return the value of the id attribute in that input tag.
I also tried to get the id by using .bytagname but as id is an attribute it is not accessible
Try:
(driver) findElement(By.xpath("//*[contains(local-name(), 'input') and contains(#name, 'qty')]")).sendKeys("100");
To answer the comment by #rrd: to be honest, I have no idea why OP uses ((Webdriver imgtags.get(i)). I don't know what that is. Normally, I just use driver.findElement[...]
Hoping that he knows what works in his framework :D
Selenium Xpath handling is not fully compliant and it does not always treat // as a synonym of descendant-or-self.
Instead try tweaking your code to use the following Xpath:
((Webdriver imgtags.get(i)).findElement(By.xpath("./descendant-or-self::input[#name='qty']")).sendKeys("100");
This will base your search off the currently selected WebElement and then look for any descendants that have a name attribute with a value of "qty".
I would also suggest storing your imgtags array as an array of WebElement e.g.
List<WebElement> imgtags = new ArrayList<>();
This is a much better idea than casting to WebDriver to be able to use .findElement(). This will cause you problems at some point in the future.

Why my Selenium web driver is not clicking on Element identified by id?

My Selenium web driver is not clicking on this tree node. I don't know exactly what we say it tree node or something else so this is image and I highlighted the element.
This right arrow part on which I want to click
And this is my code:
//wait.until(ExpectedConditions.elementToBeClickable(By.id("iconDiv")));
WebElement taskdropElementid = driver.findElement(By.id("iconDiv"));
System.out.println(taskdropElementid.getAttribute("class"));
if(taskdropElementid.getAttribute("class").equals("RightArrow"))
taskdropElementid.click();
Printing statement is giving me output dropdown. I think it should give RightArrow and when I am uncommenting wait part then it is continuously wait for the element to be clickable.
What am I doing wrong?
Printing statement is giving me output dropdown
That means there are multiple elements with the same id iconDiv and unfortunately you're locating other element instead which has class name dropdown.
If you want to locate element with class name RightArrow, You should try using By.cssSelector() to locate it uniquely as below :-
WebElement taskdropElementid = driver.findElement(By.cssSelector("div#iconDiv.RightArrow"));
taskdropElementid.click();

How to locate an element using selenium webdriver which doesn't have unique identifier like Name, Id, title etc?

I am new to Selenium. Not sure how to handle this scenario. I am working on a website which has several buttons with following code,
<a class="Some big class name" datacommunication="SelectItem" token="some token number" model-id="Id1" element="button">
<i class="classname">Book Ticket</i>
</a>
<a class="Some big class name" datacommunication="SelectItem" token="some token number" model-id="Id2" element="button">
<i class="classname">Book Ticket</i>
</a>
I tried to click on it using following commands,
ele = driver.FindElement(By.ClassName("Some big class name")); but it fails with following message, Compound class names are not supported. Consider searching for one class name and filtering the results.
ele = driver.FindElement(By.CssSelector("a[model-id='Id1']")); fails with 'Test method TestBot.HomeTest.bookTicket threw exception:
OpenQA.Selenium.WebDriverTimeoutException: Timed out after 10 seconds'
Tried using XPATH,
ele = driver.FindElement(By.XPath("\\\a[#model-id='Id1']")); doesn't work either.
I have no control on html. Can't change it.
Please let me know how to identify elements in such scenarios.
You can't have spaces in class names. Those are actually multiple classes separated by a space. You can find the above elements using a css selector
var ele = driver.FindElements(By.CssSelector(".Some.big.class.name"))
Of course, this will find both elements. To find just the first, you could use
var ele = driver.FindElement(By.CssSelector("a[model-id='Id1']"))
You can find help on css selectors here: http://www.w3schools.com/cssref/css_selectors.asp
Update:
I just noticed your XPath appears to have the slashes the wrong way around. If you wish to use XPath, try
//a[#model-id='Id1']
Note, however, that css selectors perform better than XPath.
There are multiple number of ways to locate your WebElement in Selenium WebDriver.
But always remember all are based on you attribute or combination of HTML tags so case could be any of them
1- First way is using id
2- 2nd one is Name
3- Class Name
4- Some time you can used Tagname
5- Some time linkText
6- Some time partial link text
7- Using xpath
8- Using css selector
So in you case we need to take help of Xpath and Css Selector
So xpath of you elements
Syntax : //[#attribute ='value of selected tag']
Example
id1: //a[#model-id='Id1']
id2: //a[#model-id='Id2']
For both element following are the css Selector
Syntax [attribute ='value']
id1:
a[model-id='Id1']
id2:
a[model-id='Id2']
http://www.slideshare.net/weekendtesting/css-selector-29312437
http://www.slideshare.net/weekendtesting/locators-in-selenium-bnt-09
Thanks a lot for help. I have used following code to overcome above mentioned issue,
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.ElementIsVisible(By.CssSelector("a[data-model-id='c5']"))).Click();
With above code, I am able to click on the button.
Thanks again for your help and knowledge sharing.
Amit
You can locate by using xpath.
WebElement ele = driver.findElement(By.xpath("//*[#class='Some big class name']"));
there is difference between findElements and findElement.
FindElement: findElement returns a single element.
FindElements : returns a list of same element.As in this example there are multiple classes with same class name , so use driver.findElements method .
driver.findElements will return a list of all elements with that class name .
Now , you have list of all elements but you want only one of the element.
So iterate over list to get a single element out of a list.
List<WebElement> elementList= driver.FindElement(By.ClassName("Some.big.class.name"));
Iterator itr = elementList.iterator();
while(itr.hasNext())
{
WebElement element = itr.next();
if(element.getAttribute("model-id").equals("Id1")){
element.click();
break;
}//if block ends here
}//while loop ends here
You can also use XPATH , if nothing works
To identify the elements in selenium there are multiple ways.
To see the details please refer BY Class.
Try to find the way which can identify the element uniquely. Start with id if available and if nothing works go for XPATH. XPATH is slower than id and CSS selector.

selenium webdriver code to click on 'Album' in facebook

I am not able to click on 'Albums' in Facebook.
The HTML is Albums how to locate the element 'Albums' in selenium web driver.
I tried with using driver.findelement(By.xpath(span[#class="_3sz"]) showing error as element not found
And, the html looks the following:
<span class="_3sz">Albums</span>
If I am understanding your problem correctly then that xpath you mentioned returns more than one elements. Use a text based search which is more easier and specific.
driver.findelement(By.xpath("//*[.='Albums']").click();
And, here . is used to directly point to the parent element. Additional wait might be needed to wait for the element to interact. Also, I am assuming you are trying to click the element.
EDIT
Driver = new ChromeDriver();
WebDriverWait wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(10));
Driver.Navigate().GoToUrl("http://www.facebook.com");
Driver.Manage().Window.Maximize();
Driver.FindElement(By.CssSelector("#email")).SendKeys("your email");
Driver.FindElement(By.CssSelector("#pass")).SendKeys("your pass");
Driver.FindElement(By.CssSelector("[type='submit'][value='Log In']")).Click();
Driver.FindElement(By.CssSelector(".fbxWelcomeBoxName")).Click();
Driver.FindElement(By.XPath("//*[.='Photos']")).Click();
wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("//*[.='Albums']")));
Driver.FindElement(By.XPath("//*[.='Albums']")).Click();
By albumname = By.XPath("//strong[.='2014']"); //this should be your album name. In my case it's 2014
wait.Until(ExpectedConditions.ElementExists(albumname));
Driver.FindElement(albumname).Click();
wait.Until(ExpectedConditions.ElementExists(By.CssSelector(".fbPhotoAlbumHeader.fbPhotoAlbumOptionsPresent [type='file']")));
Driver.FindElement(By.CssSelector(".fbPhotoAlbumHeader.fbPhotoAlbumOptionsPresent [type='file']")).SendKeys(#"D:\Users\Saifur\Desktop\FacebookPicture\150232_585410621540701_1836495431_a.jpg");
wait.Until(ExpectedConditions.ElementExists(By.CssSelector(".pvm.phl.footerBox.uiBoxWhite")));
Driver.SwitchTo().ActiveElement();
wait.Until(ExpectedConditions.ElementExists(By.CssSelector("[name='postPhotosButton']")));
Driver.FindElement(By.CssSelector("[name='postPhotosButton']")).Click();
Notice mine is C#
It always best practice to follow this sequence while selecting elements.
1) ID
2) CSS
3) XPath (This will have some issues with different browsers specially IE)
In this case, considering this is no other span class with same name. It would have work like this "span._3sz". Simple and powerful.