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
}
}
Related
I am wanting to create a custom method in a Base page object that will allow me to validate the results returned in a dynamic table after searching.
I have the below method ..
It takes as arguments the WebElement table, a column name that I want to validate against and and expected value that I expect to be returned by a row of that column.
I am trying to find the column index of the column with name that I pass in as columnName and assign it to a variable called searchedColIndex then use this to get all values returned under that column and then validate whether the expected result was in the list.
However I am not sure how to get the index of the column.
Also I never seem to get inside the if statement, even though when I print both column.getText() and columnName to console the values are correct and should match for one of columns, but that if statement is never evaluated as true.
public void validateTableData2(WebElement table,String columnName, String expectedSearchResult){
List<WebElement> tableRows = table.findElements(By.xpath(".//tr"));
List<WebElement> tableColumns = table.findElements(By.tagName("th"));
int searchedColIndex = 1;
for (WebElement column : tableColumns) {
if(column.getText().trim() == columnName.trim()){
System.out.println("We don't get in this if statement");
System.out.println("The values in column headers are available as if I print column.getText() then it does return correct column headings");
//Not sure how I can assign the index of the column I am interested in
//column.getText() does
}
}
List<String> returnedVals = new ArrayList<String>();
for (int i = 1; i < tableRows.size(); i++) {
String returnedVal = table.findElement(By.xpath("./tbody/tr["+i+"]/td["+searchedColIndex+"]")).getText();
returnedVals.add(returnedVal);
}
Assert.assertTrue(returnedVals.contains(expectedSearchResult));
}
Any help would be much appreciated.
For your second question, use equals() instead of ==, then you should get inside the if statement.
I was able to come up with the below method, which seems to work, although perhaps won't work for every table I try to use it with ..
public void validateTableData2(WebElement table,String columnName, String expectedSearchResult){
List<WebElement> tableRows = table.findElements(By.xpath(".//tr"));
System.out.println("Col name is " +columnName);
int searchedColIndex = table.findElements(By.xpath("//thead/tr/th/a[text()='"+columnName+"']/../preceding-sibling::th")).size()+1;
List<String> returnedVals = new ArrayList<String>();
for (int i = 1; i < tableRows.size(); i++) {
String returnedVal = table.findElement(By.xpath("./tbody/tr["+i+"]/td["+searchedColIndex+"]")).getText();
System.out.println("Returned val is "+returnedVal);
returnedVals.add(returnedVal);
}
Assert.assertTrue(returnedVals.contains(expectedSearchResult));
}
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...
I am trying to develop a method which receives a List of ArrayList and classify the array list inside it based on the object value. Then, return array list that contains the objects have 1 in their FirstChoice.
the data structure in my code is that
the List has n number of ArrayList, the ArrayList has 24 objects. each object has 3 elements and FirstChoice is one of these elements.
The problem of my code is the output not as i expect , it seems to be just stick with one value and repeat it for the whole list. could you please help me to fix that
ArrayList<HH> TestMethods(List<ArrayList<HH>> s) {
ArrayList<HH> scenario = new ArrayList<HH>();
for (ArrayList<HH> d : s) {
for (int i = 0; i < d.size(); i++) {
if (s.get(i).get(i).FirstChoice == 1) {
scenario.add(s.get(i).get(i));
}
}
}
return scenario;
}
The problem in your code is that when you are looping over the list s, you are actually never using the current element d.
Some other comments on your code:
Prefer returning a List instead of an ArrayList.
Name your methods and variables according to Java naming conventions (testMethods instead of TestMethods, firstChoice instead of FirstChoice)
Be consistent in the way you write loops: use foreach or an index but keep to the same style.
List<HH> testMethods(List<ArrayList<HH>> s) {
List<HH> scenario = new ArrayList<HH>();
for (ArrayList<HH> d : s) {
for (HH hh : d) {
if (hh.firstChoice == 1) {
scenario.add(hh);
}
}
}
return scenario;
}
Your mistakes are on these lines if (s.get(i).get(i).FirstChoice == 1) { and scenario.add(s.get(i).get(i)); as you aren't actually user inner list d.
You're referencing the i'th element of the i'th list of s, when I think you want the i'th element of d where d is a list from s.
ArrayList<HH> TestMethods(List<ArrayList<HH>> s) {
ArrayList<HH> scenario = new ArrayList<HH>();
for (ArrayList<HH> d : s) {
for (int i = 0; i < d.size(); i++) {
int item = d.get(i).FirstChoice;
if (item == 1) {
scenario.add(item);
}
}
}
return scenario;
}
How to delete the content of an array of objects. If there is other ways to delete a content of an array of objects , please do share.
import java.util.Arrays;
import java.util.Scanner;
import org.apache.commons.lang3.ArrayUtils;
public class Testing {
public static void deleteItem(ItemTracker[] listItems) {
System.out.println("Which item you want to delete? ");
for(int i=0; i < listItems.length; i++) {
if(input.equalsIgnoreCase("Quantity")) {
// Some Code
} else if(input.equalsIgnoreCase("Something"){
ArrayUtils.remove(listItems, i); // This is the part where it should delete .. but it doesnt delete.
}
break;
}
}
}
Change this
ArrayUtils.remove(listItems, i);
to
listItems = ArrayUtils.remove(listItems, i);
As you can see in the JavaDoc, the method does not change the argument listItems, rather it returns a new array with the remaining elements.
Edit
You also need to change your deletion method to
public static ItemTracker[] deleteItem(ItemTracker[] listItems) {
//..
}
So you could return the new array with the remaining elements.
Store the resulting array.
It won't change the original array object.
listItems = ArrayUtils.remove(listItems, i);
Edit: But for using this method you need the change to return type of your method
public static ItemTracker[] deleteItem(ItemTracker[] listItems){
System.out.println("Which item you want to delete? ");
for(int i=0; i < listItems.length; i++) {
if(input.equalsIgnoreCase("Quantity")) {
// Some Code
} else if(input.equalsIgnoreCase("Something"){
listItems = ArrayUtils.remove(listItems, i); // This is the part where it should delete .. but it doesnt delete.
}
break;
}
return listItems;
}
In your case usage of ArrayUtils is incorrect and redundant. You can delete element in next way:
// ...
listItems[i] = null;
// array will looks like [o1, o2, null, o3, o4, ...]
// ...
There is no other way without changing method's return type
Without additional libraries, with temporary list:
Element arrayToRemoveFrom[];
Element toRemove; // should be known already
ArrayList<Element> tmpList = new ArrayList<Element>(Arrays.asList(arrayToRemoveFrom));
tmpList.remove(toRemove);
// any other code processing and removing elements
arrayToRemoveFrom = tmpList.toArray(new Arrays[tmlList.size()]);
ArrayUtils.remove
This method returns a new array with the same elements of the input
array except the element on the specified position. The component type
of the returned array is always the same as that of the input array.
So,you should use it like this
listItems = ArrayUtils.remove(listItems, i);
NOTE
Here we have assign the returned array to current listItem.
As this method does not change the actual array but returns the changed array after removal same as #replace method works for String.
YES. I agree with zvdh I have missed the purpose of your method
because I was more concentrated on removal of element.Sorry for that!!
as this will not actually change the listItem and you need to return the new array which contains the change.
class Arrays
{
public static void main(String[] args)
{
double[] numbers = {6.0, 4.4, 1.9, 2.9, 3.4, 3.5};
java.util.Arrays.sort(numbers);
System.out.print("Ascending order= ");
for (int i = 0; i < numbers.length; i++)
System.out.print(numbers[i] + " ");
System.out.println();
System.out.print("Decending order= ");
for (int i = numbers.length -1; i >= 0; i--)
System.out.print(numbers[i] + " ");
}
}
This solution only displays in reverse order, but it can be changed to reorder the array using the same loop.
Hi community I have a question, I happen to have an array of objects loaded on startup, through that generate array another array of integers that contains your code, it appears that array of integers'm removing their values, what I want is to compare the list of integer array currently have with the array of objects, and remove all code object that whole array mentioned is found.
My code java:
private List<ValidColumnKey> columnCustomer;
private int[] selectedCustomer;
public void init(){
this.setColumnCustomer(new ArrayList<ValidColumnKey>());
this.getColumnCustomer().add(new ValidColumnKey(1, "Codigo", "code"));
this.getColumnCustomer().add(new ValidColumnKey(2, "Nombre", "name"));
this.getColumnCustomer().add(new ValidColumnKey(3, "Nombre Comercial", "comercialName"));
this.getColumnCustomer().add(new ValidColumnKey(4, "Estado", "isActive"));
this.setSelectedCustomer(new int [this.getColumnCustomer().size()]);
int i = 0;
for(ValidColumnKey column : this.getColumnCustomer()){
this.getSelectedCustomer()[i] = column.getCodigo();
i++;
}
}
I mean I would have my array of integers with codes removed, like this:
selectedCustomer = [1, 2, 3];
What I wanted was to remove from the list of objects that do not have codes in the array of integers, but it is not my code:
List<ValidColumnKey> auxRemoColumnKeys = new ArrayList<ValidColumnKey>();
for(ValidColumnKey column : this.getColumnCustomer()){
for(Integer codigo : this.getSelectedCustomer()){
if (column.getCodigo() != codigo) {
auxRemoColumnKeys.add(column);
break;
}
}
}
this.getColumnCustomer().remove(auxRemoColumnKeys);
I could guide the solution.
this.getColumnCustomer().remove(auxRemoColumnKeys);
This statement assumes you have a valid equals method for your class ValidColumnKey, which I suspect is probably not the case.
What you want to do is iterate with a Iterator. Some sample code could be like
Set<Integer> toRemoveCodes = new HashSet<Integer>(Arrays.asList(1, 2, 3));
for (Iterator<ValidColumnKey> it = this.getColumnCustomer().iterator(); it.hasNext(); ) {
ValidColumnKey curColumnKey = it.next();
Integer code = curColumnKey.codigo();
if (toRemoveCodes.contains(code)) {
it.remove();
}
}
There are multiple reasons your current attempt is failing. The first is that this line:
if (column.getCodigo() != codigo) {
Is testing for object equivalence between Integers, not value equavalence between ints. If you want to compare Integers, you have to use the equals method:
if (!column.getCodigo().equals(codigo)) {
However, if getCodigo returns an int and getSelectedCustomer returns an int[] then this line should be changed instead:
for(int codigo : this.getSelectedCustomer()){
Because you didn't need to use Integer in the first place.
Secondly, this line attempts to remove auxRemoColumnKeys itself so you probably mean removeAll:
this.getColumnCustomer().remove(auxRemoColumnKeys);
Lastly, your logic is generally flawed. It basically says "for each element in getColumnCustomer, if getCodigo is not equal to all of getSelectedCustomer remove it". I don't think that's what you've intended.
This is a modified loop that uses the same "add to a list and remove the list items" procedure but the logic will work:
List<ValidColumnKey> auxRemoColumnKeys = new ArrayList<ValidColumnKey>();
int[] selected = this.getSelectedCustomer();
for (ValidColumnKey column : this.getColumnCustomer()) {
int i = 0;
for ( ; i < selected.length; i++) {
/* note: if getCodigo returns an Integer change this check to
* "if (column.getCodigo().equals(selected[i])) {"
*/
if (column.getCodigo() == selected[i]) {
break;
}
}
/* this says "if the search loop did not break early" */
if (i == selected.length) {
auxRemoColumnKeys.add(column);
}
}
this.getColumnCustomer().removeAll(auxRemoColumnKeys);