GroovyCastException in Katalon when performing Selenium explicit wait - selenium

I am trying to perform an explicit wait in Katalon (which uses Groovy). I have the following code :
// wait on page change to "Dashboard"
WebDriverWait dashboardChangeWait = new WebDriverWait(driver, 3)
/* This is causing the following Exception :
* - GroovyCastException : Attempt to cast 'true' with class 'java.lang.Boolean' to class
* 'org.openqa.selenium.WebElement'
* */
WebElement element = dashboardChangeWait.until(
ExpectedConditions.textToBe(By.cssSelector('.breadcrumb-item.active'), "DASHBOARD"))
which is giving me a GroovyCastException. I know that WebDriverWait.until takes a Function (yay, JavaScript-like coding!) argument, and that ExpectedConditions.textToBe returns a ExpectedCondition<Boolean> and until's signature is V org.openqa.selenium.support.ui.FluentWait.until(Function<Object, Object<V>> arg0) . Is there a way to perform this type of wait in Katalon, that avoids this issue?

You were pretty close. The ExpectedConditions method textToBe() is defined as follows:
public static ExpectedCondition<java.lang.Boolean> textToBe(By locator, java.lang.String value)
An expectation for checking WebElement with given locator has specific text
Parameters:
locator - used to find the element
value - used as expected text
Returns:
Boolean true when element has text value equal to #value
So you just need to change the return type to boolean instead of WebElement as follows:
Boolean status = dashboardChangeWait.until(ExpectedConditions.textToBe(By.cssSelector('.breadcrumb-item.active'), "DASHBOARD"))

Related

Getting error as java.lang.NullPointerException while iterating webelement from Set<WebElement> using FindAll and PageObject

I was trying to automate to select drop down option with set<WebElement> , but while iterating it gives error as NullPointerException . I same tried with List<WebElement> , It works fine.
UserPageObject.java
----------------------------
#FindAll({#FindBy(xpath ="//li[#role='option']/span[#class='ng-star-inserted']")})
private Set<WebElement> DropDownElementStatus;
public Set<WebElement> getDropDownElementStatus() {
return DropDownElementStatus;
}
public void setDropDownElementStatus(Set<WebElement> dropDownElementStatus) {
DropDownElementStatus = dropDownElementStatus;
}
ActionsUtilities.java
---------------------------
public void AllDropDownSetElements(Set<WebElement> dropDownsElements, String DropDownOption ){
Iterator<WebElement> dropDownIteratorElements= dropDownsElements.iterator(); //getting error as NullPointerException on this line
while(dropDownIteratorElements.hasNext())
{
WebElement element= dropDownIteratorElements.next();
if(element.getText().trim().equals(DropDownOption))
element.click();
}
}
UserStepDefifnation.java
-----------------------------
objectList.getActionsUtilities().AllDropDownSetElements(objectList.getUserPageObject().getDropDownElementStatus(),"INACTIVE");
Just like findElements() returns a List of WebElements:
java.util.List<WebElement> findElements​(By by)
Annotation Type FindAll() is used to mark a field on a Page Object to indicate that lookup should use a series of #FindBy tags. It will then search for all elements that match any of the FindBy criteria. However, elements are not guaranteed to be in document order.
#FindAll({#FindBy(xpath ="//li[#role='option']/span[#class='ng-star-inserted']")})
private List<WebElement> DropDownElementStatus;
It can be used on a types as well as follows:
#FindAll({#FindBy(how = How.ID, using = "foo"),
#FindBy(className = "bar")})
To conclude, #FindAll would return a List but not a Set, which you have to incorporate within yours tests.

Selenium After sendkey, do some validation

I'm new to Selenium, TestNG and Stackoverflow.
After sendkeys, I want to do some validation. If the validation is true, then the assert is true. I know this is not the right way to write the Assert method.
WebDriver driver;
#DataProvider(name= "testdata")
public static Object[][] loginData(){
return new Object[][]{{"username1", "123"}, {"username2", "4211"}};
}
#BeforeTest
public void configure(){
....
}
#Test(dataProvider = "testdata")
public void testmethod(String uname, String password){
WebElement usernameTextbox = driver.findElement(By.id("username"));
usernameTextbox.sendKeys(uname);
WebElement passwordTextbox = driver.findElement(By.id("username"));
passwordTextbox.sendKeys(uname);
driver.manage().timeouts().implicitlyWait(2, TimeUnit.MICROSECONDS);
Assert.assertTrue(if(usernameTextbox.contains("[a-zA-Z0-9]+") && passwordTextbox.contains("[0-9]+") == true));
PS: Any inputs will be appreciated.
Try implementing explicit wait in Your code. What that mean, is that You wait for some condition to be set, here is example how to manage this:
But my suggestion is that You assert if there are some error messages (labels, span, or whatever that appears saying something is wrong with email or pass)
So here is how I would do it:
WebDriver driver;
#DataProvider(name= "testdata")
public static Object[][] loginData(){
return new Object[][]{{"username1", "123"}, {"username2", "4211"}};
}
#BeforeTest
public void configure(){
driver = new WebDriver();
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS); //this is wait which will wait until driver throws exception (that is not found eg."NoSuchElementException")
}
#Test(dataProvider = "testdata")
public void testmethod(String uname, String password){
WebElement usernameTextbox = driver.findElement(By.id("usernameID"));
usernameTextbox.sendKeys(uname);
WebElement passwordTextbox = driver.findElement(By.id("passwordID"));
passwordTextbox.sendKeys(password); //here is where You've sent wrong param
// if You know You will get error label or something use this
WebDriverWait wait = new WebDriverWait(driver, 10); //wait for max 10 sec, and wait for error element defined bellow
WebElement errorElement = wait.until(ExpectedConditions. presenceOfElementLocated(By.id("someErrorElementId"))); //(or ExpectedConditions.textToBePresentInElement(..)), see what better suites You
// If You're expecting error than use this assert
Assert.assertTrue(errorElement.isDisplayed(),"There should be error message!")
// but If You're expecting that there should not be any error than use this assert
Assert.assertFalse(errorElement.isDisplayed(),"There shouldn't be no error messages!")
}
tweak this code, but basicaly this is the logic.
So to try to answer the original question your code could look like below:
1. Using the getAttribute("value")
2. Building the assertion - you don't need to wrap the condition in an if as the contains() function will return true or false for you:
WebDriver driver;
#DataProvider(name= "testdata")
public static Object[][] loginData(){
return new Object[][]{{"username1", "123"}, {"username2", "4211"}};
}
#BeforeTest
public void configure(){
....
}
#Test(dataProvider = "testdata")
public void testmethod(String uname, String password){
WebElement usernameTextbox = driver.findElement(By.id("username"));
usernameTextbox.sendKeys(uname);
WebElement passwordTextbox = driver.findElement(By.id("username"));
passwordTextbox.sendKeys(uname);
driver.manage().timeouts().implicitlyWait(2, TimeUnit.MICROSECONDS);
Assert.assertTrue(usernameTextbox.getAttribute("value").contains("[a-zA-Z0-9]+") && passwordTextbox.getAttribute("value").contains("[0-9]+"));
HTH
As per your question just after invoking sendKeys() you want to do some assertions.
At this point it is worth to mention that when you invoke sendKeys() on a <input> node/tag/field the HTML DOM is not immediately updated with the value / characters which you have just entered in majority of the cases (of-coarse there are exceptional cases). Moving forward when you invoke click() or submit()on a <button> or similar <input> element, the associated onclick event of this <input> element updates the HTML DOM and the value / characters previously sent through sendKeys() are adjusted within the HTML DOM.
Unless the value / characters are not accommodated within the DOM Tree Selenium won't be able to interact with them.
As per your code block, you have populated the passwordTextbox field with the String value of uname as follows :
passwordTextbox.sendKeys(uname);
This value / characterset is still volatile and editable (can be overwritten/cleared/deleted) as follows :
passwordTextbox.clear();
passwordTextbox.sendKeys("Emma E");
Essentially, Assert methods can be invoked on text those are part of the HTML DOM. As an example you can use the following Assert for a Page Heading, Table Heading, etc :
Assert.assertTrue(if(pageHeaderElement.contains("[a-zA-Z0-9]+") && tableHeaderElement.contains("[0-9]+") == true));

What is the return type of driver.findelement /driver.getwindowhandles()?

What is the return type of driver.findelement
and what is the return type of driver.getwindowhandles()?
findElement()
findElement() method finds the first WebElement using the given method. So it returns a WebElement.
An Example :
WebElement field = driver.findElement(By.xpath("//button[#class='btn']"));
getwindowhandles()
getwindowhandles() method returns a set of window handles which can be iterated over all open windows through the WebDriver instance by passing them to switchTo() function.
An Example :
Set<String> mySet= driver.getWindowHandles();
In C# FindElement() returns a WebElement, which is the representation of an element on a page:
WebElement frame = driver.findElement(By.tagName("iframe"));
WindowHandles() returns a string representation of the window handle of the current driver:
foreach (string handle in driver.WindowHandles) {
driver.SwitchTo().Window(handle);
}
This link saved me lots of time when I worked in selenium years ago.
List<webelement> lt = driver.findElements(By.locator);
Set<String> set= driver.getWindowHandles();
driver.findelement returns WebElement
driver.getwindowhandles returns Set of Windows
findelement returns the object of the first matching element of the specified locator. So, it's return type is an object.
findelements's return type is an array.
Signature of findElement methid is as below.
WebElement findElement(By by)
So it should return reference of WebElement Interface.

WebDriverEventListener and loggin sendKeys data

I have been using WebDriverEventListener to log various message and one of them is the data used by sendKeys method. API -org.openqa.selenium.support.events.WebDriverEventListener#beforeChangeValueOf can be used to log messages before keying in data in text field. But I get access to only element locator using WebElement argument. Is there a way to also access data which is keyed in to element?
Before change method you are providing element locator, so you get the value as you do for an input field. Implement the beforeChangeValueOf method as follows-
public void beforeChangeValueOf(WebElement element, WebDriver arg1) {
System.out.println("Before change: "+element.getAttribute("value"));
}
Use the method:
public void afterChangeValueOf(WebElement element,
WebDriver driver,
java.lang.CharSequence[] keysToSend);
keysToSend parameter will give you the keyed data.

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);