Multiple values in css selector with Java and selenium - java

I need to get all elements with a class inside a wrapper div. I have done this before with php and the css selector would look something like this:
$this->elements($this->using('css selector')->value('div.active tr[class="theRow"]'));
Now this would give me all foo elements inside the wrapper active but I dont know how to do it with Java. I want a list with all the webElements like so:
List<WebElement> list = driver.findElements(By.cssSelector(".active,.theRow"));
This however will give me all theRow elements, eaven those outside the active wrapper. any sugestions?
the code below also give all theRow elements as expected:
List<WebElement> list = driver.findElements(By.className("theRow"));
but this gives me a empty list
List<WebElement> list = driver.findElements(By.cssSelector("tr[class='row-hover']"));

Is there a chance the class attribute of the span contains multiple values?
If so, then you may have problems using 'class=' as it would not match elements which have two or more classes.
If so, then try this;
List<WebElement> list = driver.findElements(By.cssSelector("div.active span.foo"));
When ever I access class outside of ".", I would always use "[class*='foo']" because you cannot guarantee the order in which multiple values appear in the class attribute, but would always use the "." notation where possible. However, whenever I use "class" in Xpath I always use "[contains(#class,'foo')] because Xpath always treats "class" as a string literal, where as CSS "." can cope with multiple values

Related

FindBys and List<WebElement> always return null list

As far as my understanding goes, FindBys Annotation in pagefactory returns you elements which satisfies all the condition mentioned inside. The code below always returns 0 elements.
Similarly,If I'm using FindAll annotation with same id and Xpath attribute it is returning me 2 webelements. Can anyone help me in understanding the results.
#FindBys
(
{
#FindBy(xpath="//*[#id='ctl00_ctl00_divWelcome']"),
#FindBy(id="ctl00_ctl00_divWelcome")
}
)
public List<WebElement> allElementsInList;
Your understanding is wrong.
The documentation for #FindBy says:
Used to mark a field on a Page Object to indicate that lookup should use a series of #FindBy tags in a chain as described in org.openqa.selenium.support.pagefactory.ByChained
Further, the documentation for ByChained says:
Mechanism used to locate elements within a document using a series of other lookups. This class will find all DOM elements that matches each of the locators in sequence, e.g. driver.findElements(new ByChained(by1, by2)) will find all elements that match by2 and appear under an element that matches by1.
So in your example, you are looking for an element by XPath with a specific ID, and then its child element by the same ID ... which, of course, is not going to return anything.

#Findby using xpath with index

Can I use #Findby and pass certain values as parameter?
#FindBy("//div[contains(#class,'gallery_grid_image_caption gallery_grid_image_caption_padding')]"[$INDEX])
I know I can do this while using findElement. Kindly let me know if there is a solution/work around.
What I want to do it is let's say there is a for loop and there is a list of elements in a page. Now let's say the only thing that is changing among these fields is the bit of the xpath. //div/1, //div/2 .... What I want to do is represent one element for all these elements and pass the ending values as parameter.
I believe what you are trying to do is something like this :
#FindBy(xpath = "//div[contains(#class,'gallery_grid_image_caption gallery_grid_image_caption_padding')]")
public WebElement yourElement;
SO-9028757 should provide you more context.

While working with Selenium webdriver, why do we use linked list for gathering links or dropdown contents with mutliple matches?

Example code is something like this, (this was an interview question asked for me recently)
List linkElements = driver.findElements(By.tagName("a"));
I would say, through List you can dynamically add, access and remove objects of the same type. Also, it won't mind even if it has No contents.
Generally you choose a Data Structure according to your needs. Here while doing a findElements() search we are saying that we want all the elements with the given structure in DOM and we can't be always sure about it's size in advance. Using a fixed sized array in such conditions won't make much sense.
I hope it helps :)
List represents an ordered list of objects, meaning you can access the elements of a List in a specific order, and by an index too. You can also add the same element more than once to a List. List allows null elements and you can have many null objects in a List
You will get all the result in a particular order one by one. It is also allow you to add duplicates. Our result can have duplicates which mainly we need in automation , but if your requirement is different and you do not need duplicates then you can use other collection type.If you use set then it will not allow duplicates and it's an unorder presentation of object.
We use List because when we are using findElements() instead of findElement() then we are expecting that locator will return us more than 1 element(Not in every case or scenario). So it's a good practice to use List so our data is saved in list in a ordered manner so we can use them properly.
Generally I am using List in below manner:-
List<WebElement> allOptions = dropDown.findElements(By."OUR Locator");
for ( WebElement we: allOptions) {
dropDown.sendKeys( Keys.DOWN ); //simulate visual movement
sleep(250);
if ( we.getText().contains( text ) ) select.selectByVisibleText("Value1");
}
You can also do it in many ways refer below:-
https://sqa.stackexchange.com/questions/8029/how-to-iterate-a-list-of-webelements-and-print-the-values-one-by-one-to-perform
Here is more detail version which help you to identify that when to use list:-
http://java67.blogspot.in/2013/01/difference-between-set-list-and-map-in-java.html
Adding and Accessing Elements
To add elements to a List you call its add() method. This method is inherited from the Collection interface. Here are a few examples:
List listA = new ArrayList();
listA.add("element 1");
listA.add("element 2");
listA.add("element 3");
You can access them via index as below:-
String element0 = listA.get(0);
String element1 = listA.get(1);
String element3 = listA.get(2);
System.out.println(element0+" "+element1+" "+element3);
Hope it will help you :)

Get value of an element of a list

I need to access the value of an element in a list in a different class. Here is how it goes:
In class DocumentManager.java:
Domain.Form form = new Domain.Form();
Services.Form wsForm = new Services.Form();
What I have not been able to do is to assign the value of versionLabel in the similar manner. I think this is because "version" is a List in "form" and String in "wsForm". I would want something like the following:
wsForm.setVersionLabel(form.getVersions().getLabel());
"label" has a String value. I want to assign that to versionLabel in "wsForm".
Thank you in advance.
You are working with a List and therefore you have to call
wsForm.setVersionLabel(form.getVersions().get(/index here/).getLabel());
What you were doing is calling a non-existing method for Lists on a List. In this way you can get to a certain Version in the list, and on this Version object you can call your getLabel method.
However, the real question here is, what index do you need? Or, put otherwise, are there multiple objects in the versions list? Because if not, you are overcomplicating things for yourself here.
Because form.getVersions() will returns List<Version> so you can't call below code:
wsForm.setVersionLabel(form.getVersions().getLabel());
If you want you can use following:
wsForm.setVersionLabel(form.getVersions().get(yourIndex).getLabel());// change index for object which you want
Note: You have to make sure which Version object's label you want to set in wsForm, In the example its just setting for first object. And make sure form.getVersions() is not null nor empty.
For last element
form.getVersions().get(form.getVersions().size()-1);
Based on your comments, that your versions increase every time someone modifies your form and if you want to get the version label of the most recent edit, you can do something like this.
int recentIndex = form.getVersions().size()-1;
wsForm.setVersionLabel(form.getVersions().get(recentIndex).getLabel());
As you're adding versions to list, the most recent version is the last version in your list, so get the label from that version

How to call a method every time a variable is called

So I have a variable that uses a method. Something like this:
By locator = By.id("something-"+getDynamicId());
Usually the id changes numbers like this: something-1 to something-2 (not those exact numbers, always different). I have a way of getting the number it changes to by calling the getDynamicId() method. The problem is, when I start my test the id is set at the start and whenever I click on a specific button, the id changes but my variable does not. Is it possible for the locator variable to call getDynamicId() everytime locator is called? Maybe everytime I click on the specific button the locator reloads?
I have looked up ClassLoaders but I do not know how to use it nor do I know if it can even do what I want.
Instead of doing that, i've gotten around dynamic ID's by using CSS.
driver.findElement(By.cssSelector("element[id^='something']"));
This means "find an <element> tag, that has an id attribute that starts with "something"
If there are multiple elements that match this, then you need to increase your specificity. You can do this by selecting some parent.
div.some-div [id^='something']
^ the space here meaning "a descendent of.."
this page may help with formulating CSS selectors like this for Selenium.
Also, in addition to what #sircapsalot has done, you can use xpath for working with dynamic ids as below (As you said in comment, there are multiple element having ids that contains "something"):
List<WebElement> elements = driver.findElements(By.xpath("//tag[contains(#id,'something-')]"));
//Say you want to click on 4th element now then use the below code(assuming the list has more than or equal to 4 elements in it)
elements.get(3).click();
Here, it will locate all the elements with tag as "tag" and has "id" that contains the text "something-" and then click on the 4th element in the list.
But, if you want to retrieve the dynamic ID and use it for clicking on the specific element, you can create a new method like this :
public static void clickOnDynamicElementById(String partial_locator_id){
//Code for getting dynamic id and then storing the retrieved dynamic ID in a string, say "dynaID";
String locator_id_to_click = partial_locator_id + dynaID;
driver.findElement(By.id("locator_id_to_click")).click();
}
Then, you can call this method directly in your main method as below:
clickOnDynamicElement("something-"); //because main method is also static, it can call the method directly.

Categories