I'm using Selenium Webdriver in Java. I have a table, and I like to get my hands on the last cell on the first row, and the last cell of last row. I manage to get one of them
WebElement table =driver.findElement(By.className("dataTable"));
List <WebElement> rows = table.findElements(By.tagName("tr"));
WebElement firstrow= rows.get(0);
WebElement lastrow= rows.get(rivit.size()-1);
List <WebElement> firstcells = firstrow.findElements(By.tagName("td"));
List <WebElement> lastcells = lastcell.findElements(By.tagName("td"));
firstcell.get(6).getText());
This is because I'm locating td-tags twice. Any hints how to get both cells nicely? I have no identifiers in my rows or cells.
You can use xpath to get the elements:
WebElement lastCellInFirstRow = driver.findElement(By.xpath("table[#class='dataTable']//tr[1]//td[last()]"));
WebElement lastCellInLastRow = driver.findElement(By.xpath("table[#class='dataTable']//tr[last()]//td[last()]"));
Here's the xpath specification. You can play with xpath here.
You can try to make it with cssSelectors:
String cssLast="table[class='dataTable']>tr:first-child>td:last-child"
String cssFirst="table[class='dataTable']>tr:last-child>td:last-child"
it will be smt like that;
driver.findElement(By.cssSelector(cssLast)).getText();
driver.findElement(By.cssSelector(cssFirst)).getText();
another approach is using js:
String getText(cssSel){
JavascriptExecutor js = (JavascriptExecutor) driver;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("var x = $(\""+cssSel+"\");");
stringBuilder.append("return x.text().toString();") ;
String res= (String) js.executeScript(stringBuilder.toString());
}
text1=getText(cssLast);
text2=getText(csscssFirst);
But always make sure that you located elements properly (e.g. using firepath, firebug addon in firefox)
The TableDriver extension (https://github.com/jkindwall/TableDriver.Java) offers a nice clean way to handle things like this. If your table has headers, you can (and should) identify the cell column by its header text, but in case you don't have headers, you can still do something like this.
Table table = Table.createWithNoHeaders(driver.findElement(By.className("dataTable")), 0);
WebElement firstRowLastCell = table.findCell(0, table.getColumnCount() - 1);
WebElement lastRowFirstCell = table.findCell(table.getRowCount() - 1, table.getColumnCount() - 1);
Related
While trying to get the menu list, I'm getting this error message:
Exception in thread "main" org.openqa.selenium.support.ui.UnexpectedTagNameException: Element should have been "select" but was "a".
Here below is the code:
public static void main(String[] args) {
// TODO Auto-generated method stub
System.setProperty("webdriver.chrome.driver", "D:\\selenium files\\chromedriver_win32_new\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("https://www.tutorialspoint.com/tutor_connect/index.php");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
WebElement ele = driver.findElement(By.xpath("//*[#id=\"logo-menu\"]/div/div[1]/div/a"));
Select s = new Select(ele);
//getting list of menu
List <WebElement> op = s.getOptions();
int size = op.size();
for(int i =0; i<size ; i++){
String options = op.get(i).getText();
System.out.println(options);
}
}
}
That is because the element you are trying to cast is a link tag and not a select tag.
You need to give the Xpath or CSS of the correct Select element and then cast it from WebElement into a Select ojbect.
In the example you are using there is not real selector, you first need to click on the buttons that says "Categories" and later take the options that appear:
WebElement button = driver.findElementByCSS("div[class='mui-dropdown']");
button.click();
WebElement SelectObj = driver.findElementByCSS("ul[class*='mui--is-open']");
Select s = new Select(SelectObj);
The desired element is not a <select> element but a <ul> element. Once you click on the <a> element then only the classname mui--is-open is appended to the desired <ul> element.
Solution
So to get the contents of the dropdown menu you need to induce WebDriverWait for the visibilityOfAllElementsLocatedBy() and you can use Java8 stream() and map() and you can use either of the following Locator Strategies:
Using cssSelector:
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("a.mui-btn.mui-btn--primary.categories"))).click();
System.out.println(new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("ul.mui-dropdown__menu.cat-menu.mui--is-open a"))).stream().map(element->element.getText()).collect(Collectors.toList()));
Using xpath:
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//a[#class='mui-btn mui-btn--primary categories']"))).click();
System.out.println(new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//ul[#class='mui-dropdown__menu cat-menu mui--is-open']//a"))).stream().map(element->element.getText()).collect(Collectors.toList()));
References
You can find a couple of relevant detailed discussions in:
How to extract the text iterating specific rows within a table using XPath with Selenium and Java
How to extract the dynamic values of the id attributes of the table elements using Selenium and Java
How to print runs scored by a batsmen in a scoreboard format webelements through CSS selector using Selenium and Java
I am stuck with the WebElement which I am trying to access on the Webpage with the below code but still getting mentioned error. The Element allows to autocomplete the subjects and multiple subjects to be entered in the single text box.
WebElement Subjects = driver.findElement(By.xpath("//*[#id='subjectsContainer']"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", Subjects);
String subject1 = prop.getProperty("subject1");
String subject2 = prop.getProperty("subject2");
String subject3 = prop.getProperty("subject3");
Subjects.sendKeys(subject1);
Subjects.sendKeys(Keys.ENTER);
Subjects.sendKeys(subject2);
Subjects.sendKeys(Keys.ENTER);
Subjects.sendKeys(subject3);
Subjects.sendKeys(Keys.ENTER);
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
WebElement accepts the multiple subjects to be entered by user which autocompletes
Selenium WebElement error
Looks like you need to add some delay or element visibility validation before you trying to send text to this element.
Additionally it's not recommended to use JavaScript click instead of WebDriver click unless you have no choice.
Please find below answer for my query as it is now working fine after putting Explict wait condition and locating correct webElement with tagname 'input'.
//Load the data from the Properties file
String subject1 = prop.getProperty("subject1");
String subject2 = prop.getProperty("subject2");
String subject3 = prop.getProperty("subject3");
//WebElement to capture the visibility condition
WebElement Subjects =driver.findElement(By.xpath("//*[#id='subjectsContainer']"));
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(Subjects)).click();
WebElement Sub1 = driver.findElement(By.xpath("//input[#id='subjectsInput']"));
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//input[#id='subjectsInput']")));
Sub1.sendKeys(subject1); //Send first Subject
Sub1.sendKeys(Keys.ENTER);
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//input[#id='subjectsInput']")));
System.out.println("ENtered subject 1" + subject1);
Sub1.sendKeys(subject2); //Send second subject
Sub1.sendKeys(Keys.ENTER);
System.out.println("ENtered subject 2" + subject2);
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//input[#id='subjectsInput']")));
Sub1.sendKeys(subject3); //Send thrid subject
Sub1.sendKeys(Keys.ENTER);
System.out.println("ENtered subject 3" + subject3);
A quick and dirty solution to many not interactable errors is simply this:
Thread.sleep(500);
I find this tactic to be extremely useful in quickly debugging problematic elements before implementing a more performant and elegant wait solution like you mentioned in your update.
I have a requirement . I am reading file from a dynamic web page , and the values which i require from the webpage lies within
<td>
, and this is visible when i inspect this element . So my question is , is it somehow possible to print the data contained in the inspect element using java?
Using JSOUP. Here is the cookbook
ArrayList<String> downServers = new ArrayList<>();
Element table = doc.select("table").get(0);
Elements rows = table.select("tr");
for (int i = 1; i < rows.size(); i++) {
Element row = rows.get(i);
Elements cols = row.select("td");
// Use cols.get(index) to get the data from td element
}
I found the solution to this one , leaving this answer in case if anyone stuck into this in future.
To print whatever you see inside inspect element can be tracked down using selenium.
Here's the code which i used `
WebDriver driver= new ChromeDriver();
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
driver.manage().window().maximize();
driver.get("http://www.whatever.com");
Thread.sleep(1000);
List<WebElement> frameList = driver.findElements(By.tagName("frame"));
System.out.println(frameList.size());
driver.switchTo().frame(0);
String temp=driver.findElement(By.xpath("/html/body/table/thead/tr/td/div[2]/table/thead/tr[2]/td[2]")).getText();
read here for more .
To get the element I have used a nested loop.I am able to click on dropdwn.PFB the code:
List<WebElement> webElements1 = driver.findElements(By.className("selectboxit"));
for(WebElement webElement1 : webElements1) {
if( webElement1.getAttribute("name").equals("TransactionHistoryFG.OUTFORMAT"))
{
WebElement web1 = webElement1.findElement(By.className("selectboxit-text"));
web1.click();
}
}
When i am trying to use Select on webelement i am getting error :
org.openqa.selenium.support.ui.UnexpectedTagNameException: Element
should have been "select" but was "span"
How can i select dropdown i span element?
Possible solution for selecting dropdown using selenium webdriver is:
Select select = new Select(driver.findElement(By.xpath("//path_to_drop_down")));
select.deselectAll();
select.selectByVisibleText("Value1");
Instead of the approach you mentioned above, let me know if this helps :)
List<WebElement> webElements1 = driver.findElements(By.cssSelect(".selectboxit"));
for(WebElement webElement1 : webElements1) {
if( webElement1.getAttribute("name").equals("TransactionHistoryFG.OUTFORMAT"))
{
WebElement web1 = webElement1.findElement(By.className("selectboxit-text"));
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("arguments[0].click();", web1);
}
}
Well, it is not the best way to do it, but in some cases it can be used:
it will open your combobox
driver.findElements(By.cssSelect(".selectboxit")).click()
now, you just need to write the specified value
driver.findElements(By.cssSelect(".selectboxit")).sendKeys("<value>");
OR
driver.findElements(By.cssSelect(".selectboxit")).sendKeys(Keys.ARROW_DOWN).
Use "ARROW_DOWN" as wanted to select your specified value.
I have tried with below coding to obtain the text from table.It works fine.But ,i want pick the data from first column alone.How can i grab the text from first column. .
WebElement tableContents = pubDriver.findElements(By.id("view_table"));
List<WebElement> rows=tableContents.findElements(By.tagName("tr"));
for(int rnum=0;rnum<rows.size();rnum++)
{
List<WebElement> columns=rows.get(rnum).findElements(By.tagName("td"));
for(int cnum=0;cnum<columns.size();cnum++)
{
System.out.println(columns.get(cnum).getText());
}
}
I have tried with below coding ,i didn't get the text from first column
columns.get(0).getText();
you can do like this....
// Create a new instance of the html unit driver
// Notice that the remainder of the code relies on the interface,
// not the implementation.
WebDriver driver = new FirefoxDriver();
// And now use this to visit Google
driver.get("http://localhost:8081/TestXmlDisplay/tabletest.html");
WebElement tableContents = driver.findElement(By.tagName("table"));
List<WebElement> rows=tableContents.findElements(By.tagName("tr"));
for(int rnum=0;rnum<rows.size();rnum++)
{
List<WebElement> columns=rows.get(rnum).findElements(By.tagName("td"));
System.out.println(columns.get(0).getText());
}
// driver.quit();