Shadow Root - click in a href under several shadow roots - java

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.

Related

Click on table row if text is found

I use this Java code with Selenium to select table row based on found text:
WebElement tableContainer = driver.findElement(By.xpath("//div[#class='ag-center-cols-container']"));
List<WebElement> list = tableContainer.findElements(By.xpath("./child::*"));
// check for list elements and print all found elements
if(!list.isEmpty())
{
for (WebElement element : list)
{
System.out.println("Found inner WebElement " + element.getText());
}
}
// iterate sub-elements
for ( WebElement element : list )
{
System.out.println("Searching for " + element.getText());
if(element.getText().equals(valueToSelect))
{
element.click();
break; // We need to put break because the loop will continue and we will get exception
}
}
Full code: https://pastebin.com/ANMqY01y
For some reason table text is not clicked. I don't have exception. Any idea why it's not working properly?
See there are 2 divs with //div[#class='ag-center-cols-container'] with this xpath.
first div does not have anything, while second div has child divs.
I would suggest you to use :
List<WebElement> list = driver.findElements(By.xpath("//div[#class='ag-center-cols-container']//div"));
Remove this line from your code :
WebElement tableContainer = driver.findElement(By.xpath("//div[#class='ag-center-cols-container']"));

I am getting StaleElementReferenceException: element is not attached to the page document

HTMLCODE
I am getting StaleElementReferenceException: element is not attached to the page document. I went through some of the solutions that are already there in StackOverflow. It did not work and it continues to throw the same error. Here is the code I am using which is throwing the stale reference error
WebElement table2 = driver.findElement(By.cssSelector("body > div:nth-child(74) > div.sp-palette-container"));
List<WebElement> allrows2 = table2.findElements(By.tagName("div"));
for(WebElement row2: allrows2){
List<WebElement> cells = row2.findElements(By.tagName("span"));
for(WebElement cell:cells){
if (cell.getAttribute("title").equals("rgb(0, 158, 236)")) {
cell.click();
}
}
}
Because clicking the found cell lead some HTML changes on the current page , due to this changes selenium will treat the page(after click) is an "new" page (even though not redirect to another page actually).
In the next iteration of the loop, the loop still refer to element belongs to "previous" page, this is the root cause of "StateElementReference" exception.
So you need to find those elements again on the "new" page to change the reference of element comes from "new" page.
WebElement table2 = driver.findElement(By.cssSelector("body > div:nth-child(74) > div.sp-palette-container"));
List<WebElement> allrows2 = table2.findElements(By.tagName("div"));
int rowSize, cellSize = 0;
rowSize = allrows2.sie();
for(int rowIndex=0;rowIndex<rowSize;rowIndex++){
WebElement row2 = allrows2.get(rowIndex);
List<WebElement> cells = row2.findElements(By.tagName("span"));
cellSize = cells.size();
for(int cellIndex=0;cellIndex<cellSize;cellIndex++){
WebElement cell = cells.get(cellIndex);
if (cell.getAttribute("title").equals("rgb(0, 158, 236)")) {
cell.click();
// find cells again on "new" page
cells = row2.findElements(By.tagName("span"));
// find rows again on "new" page
allrows2 = table2.findElements(By.tagName("div"));
}
}
}
If your usecase is to click() on the elements with title as rgb(0, 158, 236) you can use the following code block :
String baseURL = driver.getCurrentUrl();
List<WebElement> total_cells = driver.findElements(By.xpath("//div[#class='sp-palette-container']//div//span"));
int size = total_cells.size();
for(int i=0;i<size;i++)
{
List<WebElement> cells = driver.findElements(By.xpath("//div[#class='sp-palette-container']//div//span"));
if (cells.get(i).getAttribute("title").contains("rgb(0, 158, 236)"))
{
cells.get(i).click();
//do your other tasks
driver.get(baseURL);
}
}
Use a "break" after clicking on the element found. The exception occurs because, after clicking on your element, the loop continues.
WebElement table2 = driver.findElement(By.cssSelector("body > div:nth-child(74) > div.sp-palette-container"));
List<WebElement> allrows2 = table2.findElements(By.tagName("div"));
for(WebElement row2: allrows2){
List<WebElement> cells = row2.findElements(By.tagName("span"));
for(WebElement cell:cells){
if (cell.getAttribute("title").equals("rgb(0, 158, 236)")) {
cell.click();
break;
}
}
}

Trying to search and return the webelement

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']

Why is this WebElement not returning the full xpath?

I have several WebElements such that executing the following
List<WebElement> customers = driver.findElements(By.xpath("//div[#id='Customers']/table/tbody/tr"));
System.out.println(customers.size());
would print 5.
So then why does the following code
List<WebElement> customers = driver.findElements(By.xpath("//div[#id='Customers']/table/tbody/tr"));
for (WebElement customer : customers) {
if (customer.getText().equals("SQA")) {
WebElement test = customer;
System.out.println(test);
break;
}
}
print xpath: //div[#id='Customers']/table/tbody/tr and fail to actually include the specific index of the path? The above xpath is absolutely useless; I'm expecting the location of where SQA was found.
xpath: //div[#id='Customers']/table/tbody/tr[4]
I think it just prints the locator used to find the element. If you want the index, just change your code to
List<WebElement> customers = driver.findElements(By.xpath("//div[#id='Customers']/table/tbody/tr"));
for (int i = 0; i < customers.size(); i++)
{
if (customers.get(i).getText().equals("SQA"))
{
System.out.println(i);
break;
}
}

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