Trying to search and return the webelement - java

I am trying to search the webelement and trying to return back like in below code. Will it work. I have multiple times after returning it traversing back to first element always. Please help me in this.
public obj1 obj2(String Name)
{
WebElement ayName = isApplicationList(Name);
if (ayName.getText().equals(Name))
{
WebElement edit = driver.findElement(By.name("action_edit_application"));
click(edit);
obj1 obj1 = obj3.method(browser, obj1.class);
return obj1.edit(Name);
}
return null;
}
//method2
public WebElement obj2(String displayName)
{
WebElement element1 = null;
WebElement Element = deriver.findElement(By.name("abcjl"));
List<WebElement> ElementList = Element.findElements(By.tagName("your tagName"));
for (WebElement sinElement : ElementList)
{
WebElement ayName = ApplicationElement.findElement(By.name("my_name"));
if (erDisplayName.getText().equals(displayName))
{
element1 = erDisplayName;
return element1;
}
}
return element;
}

why don't you use XPath or CSS to find the element you are interested an click on it rather than iterate all the child elements.
This will find the element with name my_name and has visible text as displayName and whose parent element has name abcjl
//*[#name='abcjl']//tagName[#name='my_name' and text()='displayName']

Related

Shadow Root - click in a href under several shadow roots

I have a list of links inside of several shadowRoots. Already solved this problem.
public WebElement expandRootElement(WebElement element) {
WebElement ele = (WebElement) ((JavascriptExecutor) driver).executeScript("return arguments[0].shadowRoot",element);
return ele;
}
WebElement root5_adminPanel = shadowRoot4_MduiContainerChild2.findElement(By.cssSelector("#layout > border-layout > ng-view > admin-panel"));
WebElement shadowRoot5_AdminPanel= expandRootElement(root5_adminPanel);
WebElement root6_breadCrumb = shadowRoot5_AdminPanel.findElement(By.cssSelector("#layout > border-layout > breadcrumb"));
WebElement shadowRoot6_breadCrumb = expandRootElement(root6_breadCrumb);
WebElement root6_domainPanel = shadowRoot5_AdminPanel.findElement(By.cssSelector("#layout > border-layout > ng-view > gdsr-domain-panel"));
WebElement shadowRoot6_domainPanel = expandRootElement(root6_domainPanel);
WebElement root7_selectDomain = shadowRoot6_domainPanel.findElement(By.cssSelector("#domainContainer > domain-panel-item.ng-binding.last"));
WebElement shadowRoot7_selectDomain = expandRootElement(root7_selectDomain);
When I reach this shadowRoot7, I have a list of items with the same name, which I already created a List to fix it.
List<WebElement> rows_table = shadowRoot6_domainPanel.findElements(By.cssSelector("#domainContainer > domain-panel-item:nth-child(n)"));
(They are around 45 items)
This will select all of them, in this case all the domain-panel-item rows.
My problem is that each domain-panel-item still contain another shadowRoot (the same path for all of them) an i would like to select a random item, not the first or last one, for example, the item number 43.
enter image description here
My solution was this one but it doesn't work because it doesnt access to the link that i want:
public void clickSelectedDomain(String domain) {
List<WebElement> rows_table = shadowRoot6_domainPanel.findElements(By.cssSelector("#domainContainer > gdsr-domain-panel-item:nth-child(n)"));
int rows_count = rows_table.size();
for (int row=0; row<rows_count; row++) {
if(rows_table.get(row).getAttribute("href").contains(domain)) {
rows_table.get(row).click();
}
}
}
Some have an idea how to fix this?
You solved the problem by calling recursively executeScript() in order to get the imbricated Shadow DOMs but actually you could have just called executeScript() once, and inside got the Shadow DOMs successively.
driver.executeScript( function ()
{
var root1 = document.querySelector( 'selector string 1' ).shadowRoot
var root2 = root1.querySelector( 'selector string 2' ).shadowRoot
var root3 = root2.querySelector( 'selector string 3' ).shadowRoot
...
return foundElement
}
Anyways, in the for() {} loop, you should extract the ultimate Shadow DOM one last time, and then select the <a> element to check its content.

Converting xpath from String to WebElement

Right now I use the below method in my BasePage and I wish to call this method to my other pages.
So in the below method, the parameter is (String xpathExpression), How do I change this to WebElement and use other element locators which will be defined in other pages.
protected boolean CheckSorting(String xpathExpression) {
List<WebElement> issueTypeDropdown = new LinkedList<>(driver.findElements(By.xpath(xpathExpression)));
LinkedList<String> issueTypes = new LinkedList<String>();
for (int i = 0; i < issueTypeDropdown.size(); i++) {
//System.out.println(issueTypeDropdown.get(i).getText());
issueTypes.add(issueTypeDropdown.get(i).getText());
}
return Compare(issueTypes);
}
You can't get the locator from WebElement. If you want the locator strategy to be dynamic you can send By to the method
protected boolean CheckSorting(By by) {
List<WebElement> issueTypeDropdown = new LinkedList<>(driver.findElements(by));
//...
}
Uses:
CheckSorting(By.xpath(xpathExpression));

Auto Suggestion list: java.lang.IllegalArgumentException: Cannot find elements when the XPath expression is null

autosuggestionselect(By.xpath(
Configurations.getSalesLocator("//ul/li/a[text()='"+InvestigationNo+"']")));
public void autosuggestionselect(By by) throws InterruptedException {
List <WebElement> Elements = driver.findElements(by);
System.out.println(Elements.size());
for (WebElement element : Elements) {
System.out.println(element.getText());
String actual = InvestigationNo;
String expected = element.getText();
Thread.sleep(5000);
if (actual.equals(expected)) {
element.click();
break;
}
}
}
This happens when I try to select an item from the auto suggestion list. Please help.

How do I refresh a stale Selenium element if I don't have the original XPath

Is there a way (If using Java) to refresh an existing element that has become stale. Something like, I have an Angular app that removes and re-adds an element. Sometimes this hits a race condition and gives me a stale state. I would like to avoid a sleep to slow things down, however, I am fine with something that tries every 500 ms or something. I see foundBy but when I try something like
driver.findElement(By.xpath(element.foundBy))
But this doesn't work. How do I refresh if I am not sure what xPath was initially used?
In case of page refresh or any change in DOM that includes your WebElement will lead to such exception. Selenium doesn't support WebElement refresh (sadly enough) so you have to locate your element again by hand, which may be pita in some cases. I use
public WebElement refreshElement(WebElement element){
String sElement = element.toString().split("-> ")[1];
String locatorType = sElement.split(": ")[0];
if (locatorType.matches("css selector")) locatorType = "css";
String loc0 = sElement.split(": ")[1];
String theLocator = loc0.substring(0,loc0.length()-1);
System.out.println("Refreshing element with "+locatorType+": "+theLocator);
return locator.getElement(theLocator,locatorType);
}
and seems to work fine since a WebElement.toString() will produce something like
[[ChromeDriver: chrome on LINUX (****************************)] -> locatortype: locator]
The getElement method goes like
public WebElement getElement(String locator, String type) {
if (type.equals("id")) {
return this.driver.findElement(By.id(locator));
}
else if (type.equals("name")) {
return this.driver.findElement(By.name(locator));
}
etc...
}
I could get over StaleElementReferenceException by extracting the locator value and refreshing the element.
/*
* Example Element Info: [[ChromeDriver: chrome on MAC (7066c356a66e3d36c02336042e9ae3bd)] -> tag name: input]
* Get locator value from Element and find again to get over StaleElementReferenceException
*/
public WebElement refreshWebElement(WebDriver webDriver, WebElement webEl) {
String elementInfo = webEl.toString();
elementInfo = elementInfo.substring(elementInfo.indexOf("->"));
String elementLocator = elementInfo.substring(elementInfo.indexOf(": "));
elementLocator = elementLocator.substring(2, elementLocator.length() - 1);
System.out.println(elementInfo);
WebElement retWebEl = null;
if (elementInfo.contains("-> link text:")) {
retWebEl = webDriver.findElement(By.linkText(elementLocator));
} else if (elementInfo.contains("-> name:")) {
retWebEl = webDriver.findElement(By.name(elementLocator));
} else if (elementInfo.contains("-> id:")) {
retWebEl = webDriver.findElement(By.id(elementLocator));
} else if (elementInfo.contains("-> xpath:")) {
retWebEl = webDriver.findElement(By.xpath(elementLocator));
} else if (elementInfo.contains("-> class name:")) {
retWebEl = webDriver.findElement(By.className(elementLocator));
} else if (elementInfo.contains("-> css selector:")) {
retWebEl = webDriver.findElement(By.cssSelector(elementLocator));
} else if (elementInfo.contains("-> partial link text:")) {
retWebEl = webDriver.findElement(By.partialLinkText(elementLocator));
} else if (elementInfo.contains("-> tag name:")) {
retWebEl = webDriver.findElement(By.tagName(elementLocator));
} else {
System.out.println("No valid locator found. Couldn't refresh element");
}
return retWebEl;
}
try something like below:
WebElement yourElement = driver.findElement(By.xpath("xpath here"));
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(500, TimeUnit.MILLISECONDS);
wait.until(ExpectedConditions.not(ExpectedConditions.stalenessOf(yourElement )));

How to use select list in selenium?

I'm trying to select an element from a select list in selenium using java with WebDriver - based syntax.
I've got the select list by
elements = driver.findElements(By.xpath("//form[#action='inquiry/']/p/select[#name='myselect']"));
if (elements.size() == 0) {
return false;
}
if (guests != null) {
//what do I do here?
}
How do I do that?
WebElement select = driver.findElement(By.name("myselect"));
Select dropDown = new Select(select);
String selected = dropDown.getFirstSelectedOption().getText();
if(selected.equals(valueToSelect)){
//already selected;
//do stuff
}
List<WebElement> Options = dropDown.getOptions();
for(WebElement option:Options){
if(option.getText().equals(valueToSelect)) {
option.click(); //select option here;
}
}
If this is slower, then consider something like
dropDown.selectByValue(value);
or
dropDown.selectByVisibleText(text);
A little side note which applies to Java:
In my case, when I was writing the test according the example of #nilesh, I got a strange error, that the constructor is invalid. My import was:
import org.openqa.jetty.html.Select;
If you happen to have similar errors, you have to correct that import to this:
import org.openqa.selenium.support.ui.Select;
If you use this second import, everything will work.
element = driver.findElements(By.xpath("//form[#action='inquiry/']/p/select[#name='myselect']/option[*** your criteria ***]"));
if (element != null) {
element.click();
}
find the option, and then click it
Try to do it like this :
//method to select an element from the dropdown
public void selectDropDown(String Value) {
webElement findDropDown=driver.findElements(By.id="SelectDropDowm");
wait.until(ExpectedConditions.visibilityOf(findDropDown));
super.highlightElement(findDropDown);
new Select(findDropDown).selectByVisibleText(Value);
}
//method to highlight the element
public void highlightElement(WebElement element) {
for (int i = 0; i < 2; i++) {
JavascriptExecutor js = (JavascriptExecutor) this.getDriver();
js.executeScript(
"arguments[0].setAttribute('style', arguments[1]);",
element, "color: yellow; border: 3px solid yellow;");
js.executeScript(
"arguments[0].setAttribute('style', arguments[1]);",
element, "");
}
}

Categories

Resources