Not able to locate a class in Selenium - selenium

I want to locate a drop down arrow using this line of code:
driver.findElement(By.className("icon-caret-down")).click();
There is nothing wrong with the code but the same class name is used for another drop down arrow which resides before it. My script points to that drop down arrow in spite me wanting it to point to this one.
I cannot use id or xpath as these are dynamically changed

Xpaths can be used if if the elements change dynamically but if you left with no other options, below snippet should help
List<WebElement> commonElem=driver.findElements(By.className("icon-caret-down"));
for(i=0;i<commonElem.size();i++){
if(i=1){ //instead you can also use commonElem.getText()=="TextVal";
commonElem.click();
break;
}
}

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 get the clicked element in selenium when we don't know what are we clicking

I am clicking with the help of following lione oc code->
actions.moveToElement(objDriver.findElement(By.id("id_popcode")),coordinates.getX(),coordinates1.getY()-1).doubleClick().build().perform();
Basically i double click at a position(x,y) in our application. Individually we cannot click that particular element bcoz it has to be clicked at particular (x,y) itself. So i want to get the properties of that clicked element(which i click using actions command which i mentioned above) liked id, classname. Can some one help me with this...kinda stuck here..........
edit:
try execute.elementFromPoint() with JavascriptExecutor to get element by coordinates
JavascriptExecutor js = (JavascriptExecutor)driver;
WebElement theElement = (WebElement)js.executeScript("return document.elementFromPoint(arguments[0], arguments[1])", coordinates.getX(), coordinates1.getY()-1);
System.out.println(theElement.getAttribute("tagName"));
System.out.println(theElement.getAttribute("class"));
old:
you are using negative value in getY()-1 which mean coordinates above the element, it maybe the parent or preceding-sibling of element try to select it using xpath
WebElement popcodeBefore = objDriver.findElement(By.xpath("//*[#id='id_popcode']/parent::*"));
// Or
// WebElement popcodeBefore = objDriver.findElement(By.xpath("//*[#id='id_popcode']/preceding-sibling::*"));
System.out.println(popcodeBefore.getAttribute("class"));
actions.moveToElement(popcodeBefore).doubleClick().build().perform();
If you have any specific text at that particular coordinates make use of it. I too had the same issue like this where I need to double click on a cell which had text 0.00%. I have done hovering action first using the text and then performed the double-click
Ignore the syntax issues since I am working on the protractor these days
browser.driver.actions().mouseMove(driver.findElement(by.xpath("//*[text()='00')]").build().perform();
and then perform the click
Still, you have issues, check if you have any attribute like ng-click which can be helpful to get the coordinates for that particular location. please always share the HTML code so that It may help us to check more deeply

Unable to recognize Element with relative xpath or other locator

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/

Selenium Web driver - loop over elements and click if matches

i'm in day 2 of my selenium class, need help in finding an efficient way of looping over elements and if matches click the link address.
I want to navigate from classFrame to navList and loop over to find the match and click.
public void switchFrames() {
driver.navigate().to("https://seleniumhq.github.io/selenium/docs/api/java/");
driver.switchTo().frame("classFrame");
/* List<WebElement> elements = driver.findElements(By.className("navList"));
for (WebElement element : elements) {
System.out.println(element.findElement(By.xpath(".//li/a")).getText());
}
*/
List<WebElement> items = driver.findElements(By.cssSelector("ul li"));
if ( items.size() > 0 ) {
for ( WebElement we: items ) {
we.findElement(By.linkText("Deprecated")).click();
}
}
driver.findElement(By.linkText("Deprecated")).click();
driver.close();
}
The main part you are missing and the reason you can't find the element you are looking for is because it's in a frame. In order to access elements in a frame with Selenium, you need to switch the driver context to the frame. You do that using driver.switchTo().frame(). Once you are done interacting with the frame, switch back to the default context using driver.switchTo().defaultContent().
Having said that... let me offer you some more advice since you are just starting out. There are several ways to do this. One way is like what you attempted... grab an element, find a child, loop through those children looking for the link you want. I prefer the more direct approach since we can search for the exact link using an XPath. What you want to do is to click the DEPRECATED link on the navbar. You could just use the By.linkText() locator and that will work but you want to be careful, especially with a page like this that has so many links, to not click on a link you didn't intend to. The way you do that is to narrow the search to the specific area you expect the link to be in, the navbar. Once you narrow the search there, you can quickly and safely find the link you are looking for. I prefer to do it in a single search using an XPath but you could use say a CSS selector to find the navbar area and then use By.linkText() to find the link, e.g.
driver.findElement(By.cssSelector("ul[title='Navigation']").findElement(By.linkText("Deprecated").click();
In that case, you will be scraping the page twice. It's not likely a big performance hit, I just prefer to use a single locator when it makes sense. I would suggest that since you are likely to use this code over and over that you put it in a function and pass it the link name, e.g.
public void clickNavbar(String linkName)
{
driver.switchTo().frame(driver.findElement(By.cssSelector("frame[name='classFrame']")));
driver.findElement(By.xpath("//ul[#title='Navigation']//a[.='" + linkName + "']")).click();
driver.switchTo().defaultContent();
}
Then you can call it like, clickNavbar("Deprecated");

Is there a way to click plain text in Codeception acceptance tests without using XPath?

Using Codeception acceptance test (with WebDriver), I would like to know if there is a way to click an element that contains a specific text, without that element being a link or a button. I know it can be done using XPath, but I'm looking for a more readable solution that uses CSS-selectors for example.
Without specific examples, probably the best you could do is to look for a group of elements using a CSS selector then loop through that collection looking for contained text. Here's a contrived example where I'm looking for a TD that contains the text "Click here".
List<WebElement> cells = driver.findElements(By.cssSelector("td.someclass"));
for (WebElement cell : cells)
{
if (cell.getText().contains("Click here"))
{
cell.click();
break; // found it, don't need to keep looping
}
}
If you want your search to look for the text, then XPath is your only option.