Extract text from multiple xpath and assert text - Selenium/Java - java

I need to find the text in an element and assert whether it matches with my required result.
The thing is, there can be n number of element from 1-100 in the page. So I can't get the xpath of all those elements and then assert the text in it.
The xpath looks like this: (from the first element)
(//DIV[#class='issues-list-item clearfix'])[1]
(//DIV[#class='issues-list-item clearfix'])[2]
(//DIV[#class='issues-list-item clearfix'])[3]
(//DIV[#class='issues-list-item clearfix'])[4]
....
(//DIV[#class='issues-list-item clearfix'])[100]
How do I loop through these xpath and assert for my text?
I tried the below method after referring few articles and it really did not help.
private static WebElement element = null;
private static List<WebElement> elements = null;
public WebElement test() throws Exception {
elements = driver.findElements(By.xpath("(//DIV[#class='issues-list-item clearfix'])[1]"));
for (WebElement element : elements) {
List<WebElement> TE = element.findElements(By.xpath("(//DIV[#class='issues-list-item clearfix'])[1]"));
if (TE.size() > 0) {
String myText = TE.get(0).getText();
if (myText.contains("High")) {
return element;
}
}
}
return null;

You can try this :
public List<WebElement> test() throws Exception {
List<WebElement> TE = new ArrayList<WebElement>();
elements = driver.findElements(By.xpath("(//DIV[#class='issues-list-item clearfix'])"));
for (WebElement element : elements) {
if(element.getText().contains("High")) {
TE.add(element);
}
}
return TE;
}
Note that , it will return a list web element which contains High as text.

The more efficient way to do this is to add your check for "High" to the locator. That way you don't have to loop through all the elements to find only the ones you want. Your locator does all that work for you and more quickly. There's also a lot less code.
public List<WebElement> test() throws Exception {
return driver.findElements(By.xpath("(//DIV[#class='issues-list-item clearfix'][contains(.,'High')])"));
}
There are a number of ways you can verify that the desired element is found. One way would be to use a TestNG Assert like
Assert.assertTrue(test().size() > 0, "Verify an element containing 'High' was found.");

//DIV[#class='issues-list-item clearfix'])[1] your query is wrong. The [1] at the end means that it will select oinly teh first item from all the items matching the query before, aka you will only compare against the first one. The second query you won't need, neitehr the if checking for size (optionally before the for loop)

Related

read subtext of an element

how can i read value of this xpath '/html/body/article/div[2]/div/div[1]/div[10]/div/div/text()[1]' in java?
findElement(By.xpath(xpath));
i can access item via chrome extention but in java it fails saying no element found. i can only access like this; '/html/body/article/div[2]/div/div[1]/div[10]/div/div' but it is not what i want.
for example for this site: https://www.milliyet.com.tr/siyaset/canikli-kararlilikla-yurumeye-devam-ediyoruz-6277692
i would like to get these items text value separately
/html/body/article/div[2]/div/div[1]/div[10]/div/div/text()[1]
/html/body/article/div[2]/div/div[1]/div[10]/div/div/span/span[1]/time
/html/body/article/div[2]/div/div[1]/div[10]/div/div/span/span[2]/time
thanks.
findElement () can only return the Web element which contains the text you may need. If you need the actual text within the element, you have to use getText() method. You will first need to find the element and use getText() method to retrieve the text.
WebElement myElement = findElement(By.xpath("/html/body/article/div[2]/div/div[1]/div[10]/div/div"));
System.out.println(myElement.getText());
Use relative XPath to fetch your data. You can use the 3 following XPath :
//div[#class='nd-article__info-block']
(//time[#datetime])[1]
(//time[#datetime])[2]
To extract the text, use getText() method :
string el1 = driver.FindElement(By.XPath("//div[#class='nd-article__info-block']")).getText();
string el2 = driver.FindElement(By.XPath("(//time[#datetime])[1]")).getText();
string el2 = driver.FindElement(By.XPath("(//time[#datetime])[2]")).getText();
You can also store the 3 results in a list with a single XPath expression :
//div[#class='nd-article__info-block']|//time[#datetime]
Code :
List<WebElement> list=driver.findElements(By.xpath("//div[#class='nd-article__info-block']|//time[#datetime]"));
List<String> els_text=new ArrayList<>();
for(int i=0; i<list.size(); i++){
els_text.add(list.get(i).getText());
System.out.println(list.get(i).getText());
}

Selenium webdriver - Iterate, find webelement and then click on it - how can I do that?

I'd like to find the webelement that has as the visible text "7000118777", however I don't know how to exactly find it in the list and then click on it.
When I iterate it shows that the index is -1 and I get the error of "productList.get(-1);" - this is not the correct one.
public void findProductAndAddToCart(String product) {
List<WebElement> productList = SeleniumDriver.getDriver().findElements(By.className("bcom--txtBold"));
for (WebElement webElement : productList) {
String elements = (webElement.getAttribute("innerHTML"));
int indexOfProduct = elements.indexOf("7000118777");
System.out.println("Indeks produktu "+indexOfProduct);
}
productList.get(-1);
As you have not provided a link to url or screenshot of your html, this is what i understand from your question that you want to click on a element from a list where visible text is "7000118777". I also believe that you located the elements correct i.e., your productList. Please refer the below code (Replace myDriver with your WebDriver) :
List<WebElement> productList = myDriver.findElements(By.className("bcom--txtBold"));
for (int i=0; i< productList.size();i++) {
String element=productList.get(i).getText();
if(element.equals("7000118777"))
{
productList.get(i).click();
}
}

How to parameterize java method to iterate on elements in a table?

I have a table with products' names which locators differs only by index. I would like to use one method to iterate on all of the elements, because the number of elements can be changed up to 10 and I need to go through them all.
#FindBy(xpath="(//*[#class=\"product-name\"])[2]")
protected WebElement productName1;
#FindBy(xpath="(//*[#class=\"product-name\"])[3]")
protected WebElement productName2;
#FindBy(xpath="(//*[#class=\"product-name\"])[4]")
protected WebElement productName3;
A method that I want to parametrize is:
public String checkProductsInCart() {
wait.until(ExpectedConditions.visibilityOf(productName1));
String productName1String = productName1.getText();
return productName1String; }
How should I do that? I would appreciate your help.
Obtain all of the product name elements in a single list:
#FindBy(xpath="//*[#class=\"product-name\"]")
protected List<WebElement> productNameElements;
Then, in your test method, you can iterate over the elements (you could use for loop with an int index if you prefer):
List<String> productsInCart = new ArrayList<>();
for (WebElement element : productNameElements) {
productsInCart.add(nameOfProductInCart(element));
}
You can alter your check method to take a WebElement as a parameter:
public String nameOfProductInCart(WebElement element) {
wait.until(ExpectedConditions.visibilityOf(element));
return element.getText();
}
Alternatively, if this doesn't work (e.g. because the product list takes time to populate), you could use the WebDriver instance and programmatically perform each check:
List<String> productNames = new ArrayList<>();
for (int i = 2; i <= 10; i++) {
WebElement element = driver.findElement(By.xpath("(//*[#class=\"product-name\"])[" + i + "]"));
wait.until(ExpectedConditions.visibilityOf(element));
productNames.add(element.getText());
}
UPDATE: To answer the question in your comment, if you want the elements, rather than their text, you can store the elements themselves in a list:
List<WebElement> productNameElements = new ArrayList<>();
for (int i = 2; i <= 10; i++) {
WebElement element = driver.findElement(By.xpath("(//*[#class=\"product-name\"])[" + i + "]"));
wait.until(ExpectedConditions.visibilityOf(element));
productNameElements.add(element);
}
Now you can access the elements individually by getting them by index from the productNameElements list:
productNameElements.get(0); // First item
This should be easier to manage than having a separate variable for each item.
Just addendum to #ELEVATE's answer, You can find element via className:
#FindBy(className = "product-name")
private List<WebElement> tableItems;
or
#FindBy(xpath="//*[#class='product-name']")
private List<WebElement> tableItems;
but this depends if this is unique identifier...

Java Selenium webdriver filling list webelement manually

first of all:
I want to fill a List manually with element.add();
Because the elements of the page I am working with is just showing a specific range of elements, I can't just load all elements in a List<WebElement>.
That's why I want to do functions to check if an element exists in my List, if it doesn't exists there I will add it.
I want to know if there is a way to iterate specific elements like element.next();
Here is the xpath I am getting my elements:
###.findElement(By.xpath(".//a[starts-with(#href, '/p/')]"));
You ca use following snippet to fulfill your requirement
public boolean isDropdownOptionExists(String optionToBeVerified, By optionWhereToBeVerified) {
boolean isOptionFound = false;
Select optionsInDropDown = new Select(driver.findElement(optionWhereToBeVerified));
List<WebElement> availableOptions = optionsInDropDown.getOptions();
for(WebElement option: availableOptions) {
if(option.getText().equals(optionToBeVerified)) {
isOptionFound = true;
break;
}
}
return isOptionFound;
}

Verify list elements by Selenium WebDriver

WebElement select = myD.findElement(By.xpath("//*[#id='custfoodtable']/tbody/tr[2]/td/div/select"));
List<WebElement> allOptions = select.findElements(By.tagName("option"));
for (WebElement option : allOptions) {
System.out.println(String.format("Value is: %s", option.getAttribute("value")));
option.click();
Object vaLue = "Gram";
if (option.getAttribute("value").equals(vaLue)) {
System.out.println("Pass");
} else {
System.out.println("fail");
}
}
I can verify one element in a list, but there are like 20 elements in a dropdown I need to verify and I do not want to use above logic 20 times. Is there any easier way to do it?
Don't use the for-each construct. It's only useful when iterating over a single Iterable / array. You need to iterate over the List<WebElement> and the array simultaneously.
// assert that the number of found <option> elements matches the expectations
assertEquals(exp.length, allOptions.size());
// assert that the value of every <option> element equals the expected value
for (int i = 0; i < exp.length; i++) {
assertEquals(exp[i], allOptions.get(i).getAttribute("value"));
}
EDIT after OP's changed his question a bit:
Assuming you have an array of expected values, you can do this:
String[] expected = {"GRAM", "OUNCE", "POUND", "MILLIMETER", "TSP", "TBSP", "FLUID_OUNCE"};
List<WebElement> allOptions = select.findElements(By.tagName("option"));
// make sure you found the right number of elements
if (expected.length != allOptions.size()) {
System.out.println("fail, wrong number of elements found");
}
// make sure that the value of every <option> element equals the expected value
for (int i = 0; i < expected.length; i++) {
String optionValue = allOptions.get(i).getAttribute("value");
if (optionValue.equals(expected[i])) {
System.out.println("passed on: " + optionValue);
} else {
System.out.println("failed on: " + optionValue);
}
}
This code essentially does what my first code did. The only real difference is that now you're doing the work manually and are printing the results out.
Before, I used the assertEquals() static method from the Assert class of the JUnit framework. This framework is a de-facto standard in writing Java tests and the assertEquals() method family is the standard way to verify the results of your program. They make sure the arguments passed into the method are equal and if they are not, they throw an AssertionError.
Anyway, you can do it the manual way, too, no problem.
You can do it like this:
String[] act = new String[allOptions.length];
int i = 0;
for (WebElement option : allOptions) {
act[i++] = option.getValue();
}
List<String> expected = Arrays.asList(exp);
List<String> actual = Arrays.asList(act);
Assert.assertNotNull(expected);
Assert.assertNotNull(actual);
Assert.assertTrue(expected.containsAll(actual));
Assert.assertTrue(expected.size() == actual.size());
public void verifyElementsInListEquals(List<WebElement> elementsList, String expectedValue) {
ArrayList<String> TextList =new ArrayList<>(); // new list to have Text from list of Webelement
for( WebElement x :elementsList){ //for each loop in JAVA
TextList.add(x.getText()); //add "x" times text to list above
}
if(TextList.contains(expectedValue)){ //check if value exist in list above
System.out.println("Value is there");
}
else{
System.out.println(" no value");
assertTrue(false); //will always stop the program here
}
}

Categories

Resources