WebElement and drive.driver little tricky - selenium

I am trying to understand what would it be the right thing to do in here and i do not fully understand it.
Take a look:
String <WebElement> a = drive.driver.getTitle(By.xpath("somelocator"));
List <WebElement> a = drive.driver.findElement(By.xpath("somelocator"));
Boolean <WebElement> a = drive.driver.switchTO(By.xpath("somelocator"));
Map <WebElement> a = drive.driver.quit(By.xpath("somelocator"));
List <WebElement> a = drive.driver.findElements(By.xpath("somelocator"));
What would it be the right thing to do? Why?

The only 2 legal expressions here are
List <WebElement> a = drive.driver.findElement(By.xpath("somelocator"));
List <WebElement> a = drive.driver.findElements(By.xpath("somelocator"));
While only 1 expression here is making sense
List <WebElement> a = drive.driver.findElements(By.xpath("somelocator"));
Because this expression:
drive.driver.findElements(By.xpath("somelocator"));
Returns a List of WebElement objects that will match what you defined on the left side List <WebElement> a
While this:
drive.driver.getTitle(By.xpath("somelocator"));
returns a single WebElement object instance so assigning a single object to a list
List <WebElement> a = drive.driver.findElement(By.xpath("somelocator"));
Will work, but will not really make sense.
Instead of that you should use something like
WebElement a = drive.driver.findElement(By.xpath("somelocator"));
While
String <WebElement> or Boolean <WebElement> a or Map <WebElement> a are simply illegal expressions.
String and Boolean are not valid collections.
Map will have to be defined for 2 object types: the key and the value, something like Map <WebElement,Integer> map while in order to add an entry to such map a you will need to write something like this:
Map <WebElement, Integer> map = new HashMap<>();
WebElement a = drive.driver.findElement(By.xpath("somelocator"));
map.put(a,1);

Related

Testing child object by the ID of parent Katalon Studio

So I am using a dynamic object and I can receive an API that lists all of the object's properties such as ID in one page, but that ID is the ID of a frame layout that is not interactable and only contains child such as textbox or error message.
what I'm trying to achieve is to know the properties of that parent object so that I can try to interact with the child, for example, the textbox EditText inside. I am able to interact with the child by using the XPath but haven't found a way to determine the parent by the determined ID.
I am trying to make automatic testing that only uses the API as a reference point to check what is the object to test so that in the future I don't have to change the test script in case of any changes in the configuration.
I can check the API for existing object properties like this:
public static checkIfExistForm1(String code){
def response = WS.sendRequest(findTestObject("Object Repository/WebService"))
def json = new JsonSlurper().parseText(response.getResponseBodyContent())
for(int i = 0;i < json.page.form.fieldset.size(); i++){
if(code.contentEquals(json.page.form.fieldset[i].control[0].id)){
return true;
break
}
}
return false;
}
and then I can make some kind of method to get the child of that object and try to interact with it
for example with this method I can select an object by XPath
public static getObjectID(String code){
//considering i know that this is the child, or creating another validation
//the child(EditText) also has ID "content-desc" that i can use
String dynamicIdPath = '//*[#content-desc="%s"]'
String xpath = String.format(dynamicIdPath,code)
TestObject to = new TestObject()
to.addProperty("xpath", ConditionType.EQUALS, xpath)
return to
}
any thoughts? thanks!

Get unique css selector from WebElement

is it possible to get a css selector of an WebElement?
eg
var optionSelectors = mutableListOf<String>()
val options = selectWebElement?.findElements(By.cssSelector("option")).orEmpty()
for(option in options){
var optionSelector = option.getSelector()
optionSelectors.add(optionSelector)
}
return toJson(optionSelectors)
Thank you in advance
You can always use Reflection to get foundBy property value like:
Field field = element.getClass().getDeclaredField("foundBy");
field.setAccessible(true);
String foundBy = field.get(element).toString();
However the nature of your question is a little bit weird, given you found the element already you should know its selector, shouldn't you? If you want to interact with the Select option values you can go for the relevant Select class which has getOptions() function.
Also consider going for Page Object Model design pattern, it is one of best practices to keep your test logic separate from UI layer

Checking dropdown option is selected or not using elementToBeSelected / elementSelectionStateToBe.

I want to check whether option in the dropdown is selected or not. Webdriver should wait until value is selected and after that perform the next operation. I tried to use elementToBeSelected / elementSelectionStateToBe but i could not make it. How to use this?
Using WebDriverWait with ExpectedCondition "elementToBeSelected" should do what you want (it calls elementSelectionStateToBe with parameter true).
If it doesn't work for you, check that the passing argument is indeed the WebElement of option you want to have selected.
The code could look like as follows:
WebElement option = driver.findElement(By.xpath("path/to/your/option[2]"));
new WebDriverWait(driver, 10)
.until(ExpectedConditions.elementToBeSelected(option));
Another option for you is creating your own condition with anonymous class, that can be for example equality of values.
final Select select = new Select(driver.findElement(By.xpath("path/to/your/select"));
new WebDriverWait(driver, 10)
.until(new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver driver) {
// this will get actual selected option and compare its value with expected value
return select.getFirstSelectedOption().getAttribute("value").equals(expectedValue);
}
});
try
WebElement searchDDwn = driver.findElement(By.xpath(".//*[#id='edit-source']"));
Select dropdown= new Select(searchDDwn);
dropdown.selectByValue("Website");
WebElement selected = dropdown.getFirstSelectedOption();
boolean elementToBeSelected = wait.until(ExpectedConditions.elementToBeSelected(selected));
System.out.println("elementToBeSelected results"+elementToBeSelected);

Selenide combines 2 ElementsCollections

I have 2 ElementsCollections namely oddTableRowItems and evenTableRowItems:
private static ElementsCollection oddTableRowItems() {
return $$(By.className("odd"));
}
private static ElementsCollection evenTableRowItems() {
return $$(By.className("even"));
}
I want to combine the 2 in order to only do a for loop once. It is row items, and only there classnames differ for styling purposes and I can only identify them through classnames.
This is how I tried to combine it - but it does not work:
ElementsCollection rowElements = evenTableRowItems();
rowElements.addAll(oddTableRowItems());
I get an:
java.lang.UnsupportedOperationException
does anybody how can I combine the 2 ElementsCollections?
The API could probably be a little bit more friendly here. But this way you can combine two ElementsCollection instances. The key here is WebElementsCollectionWrapper class.
ElementsCollection evenElements = $$(By.className("even"));
ElementsCollection oddElements = $$(By.className("odd"));
List<SelenideElement> elementsCombined = new ArrayList<>(evenElement);
elementsCombined.addAll(oddElements);
WebElementsCollectionWrapper wrapper = new WebElementsCollectionWrapper(elementsCombined);
ElementsCollection selenideCollectionCombined = new ElementsCollection(wrapper);
All add* methods throw UnsupportedOperationException by design. It's because ElementsCollections represents a collection of existing web elements on a web page; and page elements cannot be modified by test. That's why you cannot add or remove elements on the page.
The easiest way is to select all matching elements at once:
$$(".odd,.even").shouldHave(size(10));
A little bit longer way is to compose a new list containing both collections:
List<String> newList = new ArrayList<String>();
newList.addAll($$(".odd"));
newList.addAll($$(".even"));
but your goal seems to be doubtful for me. You will get the list with invalid order. Why can it be useful? Why would one need to iterate all elements? I cannot imagine a use case for that.
According to the API:
Note that this implementation throws an UnsupportedOperationException unless add(int, E) is overridden.
You can try this code. This is work fine!
ArrayList<SelenideElement> newList = new ArrayList<SelenideElement>();
newList.addAll(Selenide.$$(By.className("odd"));
newList.addAll(Selenide.$$(By.className("even"));

List<dynamic>.Find and List<dynamic>.FindAll

I am trying to do this but unable to find a workaround.
I have a list of dynamic objects and its like ObjectList : List<dynamic>
its filled with objects that have a dynamic property LastName.
i am trying to find all elements that have a matching string in the Name property.
var result = mylist.FindAll(e => e.LastName.StartsWith("Mc"));
But when i do so, it says "Expression cannot contain lambda expressions".
you cannot use it like lambda if it dynamic try using it in different style
var result = mylist.FindAll(e => e.LastName.StartsWith("Mc"));
something like this should help
var result=(from c in mylist where c.LastName.StartsWith("Mc") select c).ToList();