How can I use the path/location of a #FindBy variable as an argument to a method?
I have the following #FindBy value in my class...
#FindBy(xpath=".//*[#id='HasAnotherSubsidisedQual_container']")
#CacheLookup WebElement mSubsidisedQual;
I then have a method for checking whether an element exists...
public boolean isElementPresent(By element){
try {
mDriver.findElement(element);
return true;
}
catch (org.openqa.selenium.NoSuchElementException e){
return false;
}
}
I then use that method in another method which contains an assertion
public void checkSmartAndSkilled () {
Assert.assertTrue(isElementPresent(By.xpath(".//*[#id='HasAnotherSubsidisedQual_container']")));
}
This all works fine, however instead of specifying By.xpath... etc in the assertion, is there anyway to pass in as an argument the path for my #FindBy WebElement mSubsidisedQual?
Many thanks
You do not need to provide the xpath again. Once it is initialized by Page Factory, simply pass the element as an argument.
public void checkSmartAndSkilled () {
Assert.assertTrue(isElementPresent(mSubsidisedQual));
}
You just created a wrong method. And the way you check element existence is wrong. But if you want to do it this way then what you should do is to overload it so the parameter is your element.
Then call the element (for example click, or use its property like Enable, or Count or Length or whatever is available in Java) and if the element doesn't exist it will catch the same error. If it exists then return true.
Related
I am getting element not found exception while trying to locate the element in a try loop. Below is my code:
private boolean isPresent(WebDriver driver,String findElement)
{
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
try {
driver.findElement(By.xpath(findElement));
return true;
}
catch (NoSuchElementException e) {
return false;
}
finally{
driver.manage().timeouts().implicitlyWait(40,TimeUnit.SECONDS);
}
}
Instead of using find element and timeouts use some waits or until for the element to be present and then do the operation.
eg. This will wait until the element is located, then do what you want to do with your myDynamicELement
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By.id("myElement")));
It looks like you are trying to validate whether your element is present or not. For that use a logic something like this.
A) Inside try
1) Wait for the element to be present
2) Then Use if then else to check if element present and return true or false
B) Inside Catch handle the error.
The better way to do this is to avoid throwing exceptions in the first place.
private boolean isPresent(WebDriver driver, By locator)
{
return !driver.findElements(locator).isEmpty();
}
Instead of passing the locator as string and requiring XPath, use a By locator. Now you can pass the method any locator type... Id, CSS selector, etc.
I want to validate the presence of a text using assertTrue(), but I am getting a StackOverflow error. I am not sure that the code I have written is correct or not. Need your suggestions.
// Checking the posted text
WebElement postedtext= driver.findElement(By.cssSelector("css123"));
assertTrue("The text is verfied",postedtext.getText().equals(enteredText));
private static void assertTrue(String string, boolean equals) {
assertTrue(string,equals);}
You have a method called assertTrue(s, b) which calls itself. This is causing an infinite recursion.
It is a name conflicting that you happened to name you assert method the same name as the library method. Rename your assertTrue can solve the problem.
// Checking the posted text
WebElement postedtext= driver.findElement(By.cssSelector("css123"));
myAssertTrue("The text is verfied",postedtext.getText().equals(enteredText));
private static void myAssertTrue(String string, boolean equals) {
try {
assertTrue(string,equals);
} catch (AssertionError e) {
System.out.println(e.getMessage());
throw e;
}
}
Or you just delete your assertTrue and use the library method instead.
I am automating a web application right now.I have used a list array to locate few objects inside a container.All I need to do is that that I have to mouse-hover to the first element and click on the same.But the mouse-hover method I have written in another class as common function.So can I use the object of the list array to pass to the mouse-hover method in any way.?
To Find the elements in the container .
By by = By.xpath("//ul[#id='sortable']");
List<WebElement> featureList= element.findElements(by.tagName("a"));
//Mouse-hover method
public static void moveMouseOver(WebDriver driver, By locator) {
WebElement element = waitForElementPresent(driver, locator);
(new Actions(driver)).moveToElement(element).build().perform();
}
Here can I change the 'By Locator' argument to replace with List array object ?
You could try changing moveMouseOver to something like :
public static void moveMouseOver(WebDriver driver, WebElement... webElements){
if(null != webElements){
for(WebElement webEl : webElements){
// do something here
}
}
}
and then call this as
moveMouseOver(driver, ((WebElement[])featureList.toArray()))
Please check for syntax errors if any as I have written this up here only and not checked in an IDE
You can change your method to:
public static void moveMouseOver(WebDriver driver, By locator, String...action) {
List<WebElement> lstElements = driver.findElements(locator);
for (WebElement webelement : lstElements){
if (action.length > 0 && action.equalsIgnoreCase("click"))
(new Actions(driver)).moveToElement(element).click().build().perform();
else
(new Actions(driver)).moveToElement(element).build().perform();
}
In such a scenario it will work for single element also and for multiple and you won't be required to change usage in previous scenarios, though u need handle different cases in future as this one handles click only.
I have two packages,one which represent class/classes for test and while other is for page object.
Inside the test class,I wanted to develop a logic where if a element is present i.e say a dropdown then follow one path and if not then follow another and then verify the results
While I see that page object pattern will be used to interact with the elements on the page then where should the logic for test go which is again dependent on the web element (dropdwwn present or not).
If we start checking the element is present or not in the test class and then pass the driver object to Page object class then wouldnt it be duplication of work.
I am not sure what should be correct approach for designing when the logic is based on whether certain webelements are present on webpage or not.
Thanks.
Write a separate class, say UTIL to hold these logic's. Also make use of this UTIL class for all your test data generation and error code handling.
The basic idea is to do something like:
try{
element.isDisplayed();
return true;
} catch(ElementNotFoundException e){
return false;
}
I've found two places for this code:
The first is in your page class that all of your pages inherit. If you don't have such a class, then a Utils class will work. Your function call will then look something like page.exists(page.getSaveButton()).
However, my favorite way (that will require a little more setup), is to write a wrapper class around WebElement (I call it EnhancedWebElement). It's constructor accepts a normal WebElement, and it redirects each function call to the WebElement, and has an exists() function.
Finally, to make every element have the exists() function, you will need to extend DefaultFieldDecorator, and override these functions:
#Override
public Object decorate(ClassLoader loader, Field field) {
if (!(WebElement.class.isAssignableFrom(field.getType())
|| isDecoratableList(field))) {
return null;
}
ElementLocator locator = factory.createLocator(field);
if (locator == null) {
return null;
}
if (EnhancedWebElement.class.isAssignableFrom(field.getType())) {
return proxyForLocator(loader, locator);
} else if (List.class.isAssignableFrom(field.getType())) {
return proxyForListLocator(loader, locator);
} else {
return null;
}
}
#Override
protected EnhancedWebElement proxyForLocator(ClassLoader loader, ElementLocator locator) {
InvocationHandler handler = new LocatingElementHandler(locator);
WebElement proxy= (WebElement) Proxy.newProxyInstance(
loader, new Class[] {WebElement.class, WrapsElement.class, Locatable.class}, handler);
return new EnhancedWebElement(proxy);
}
To implement it, wherever you call initElements, call this:
PageFactory.initElements(new EnhancedFieldDecorator(new DefaultElementLocatorFactory(driver)), this);
//Replace EnhancedFieldDecorator with the name of your decorator
This may be more than you are asking for, and if it is, that top function is what you are looking for.
I just want to check if the element is present on the page or not?
I am confused with what can be used. What is feasible to use isDisplayed() or isPresent()?
What is the difference between these two?
There is no isPresent function
The isDisplayed returns True only if the element is displayed on the webpage and is actually visible.
If you just want to check if the element is present then you can do one of the following:
Put the code for findElement inside a try/catch block. If it goes inside catch with NoSuchElementException then the element is not present.
Do findElements instead of findElement and if length of the list returned by findElements is zero, then the element is not present.
In both the cases you need to make sure that you are finding the desired element using a unique selector.
to simplify.. I've posted code below
public static boolean isElementPresent(final WebDriver driver, By by) {
try {
waitForElement(driver, by, 2);
driver.findElement(by);
return true;
} catch (NoSuchElementException e) {
return false;
}
}