Adding isExists function to WebElement - java

I want to extends selenium and implement something like this:
public class IsExistsWebElement extends WebElement {
public boolean isExists() {
try {
this.getText();
return true;
} catch (NoSuchElementException e) {
return false;
}
}
}
And then using it like this (using page factory):
public class HomePage{
#FindBy(class = "button")
private IsExistsWebElement button;
public HomePage(WebDriver driver) {
PageFactory.initElements(driver, this);
}
public boolean isButtonExists() {
return this.button.isExists();
}
}
What is the best way to implement something like this?

If you are looking for custom implementation then you have to create a new framework on top of selenium and have to write your own implementation for most of the things.
For example RemoteWebElementclass implements the WebElement interface. But its not simple to write just below code and have the access as we do for WebElement
e.g. IsExistsWebElement element = driver.findElement(By.id("a"));
class IsExistsWebElement extends RemoteWebElement {
public boolean isExists() {
try {
this.getText();
return true;
} catch (NoSuchElementException e) {
return false;
}
}
}
If you are looking for new framework on top of selenium and can afford the time(may be 3,6,9.. months depends on resources) and cost then happily go for it.
OR
Looking for managing the wait in generic way in page object model then
Create a BasePage class
Initiate explicit wait in constructor
Create wait methods for presence, visibility and so on
Extend this BasePage class in your other page class
e.g
public BasePage(WebDriver driver) {
this.driver = driver;
wait = new WebDriverWait(driver, TIMEOUT, POLLING);
PageFactory.initElements(new AjaxElementLocatorFactory(driver, TIMEOUT), this);
}
public void waitForElementReady(WebElement element) {
try {
wait.until(ExpectedConditions.visibilityOf(element));
} catch (TimeoutException exception) {
System.out.println("Element didn't find in given time");
}
}

Related

Selenium WebDriverWait.until(invisiblityOfAllElements) returns timeout on NoSuchElementException

I have a code which waits for a time for element to disappear
new WebDriverWait(driver, 10).until(ExpectedConditions.invisibilityOfAllElements(elements));
Which internally calls Selenium's
isInvisible(WebElement element)
and isInvisible is defined as follows
try {
return !element.isDisplayed();
} catch (StaleElementReferenceException ignored) {
// We can assume a stale element isn't displayed.
return true;
}
Note: It only catches StaleElementReferenceException
and in isDispalyed when the element is referenced, pagefactory package's ElementLocator class's findElement is called method which throwsNoSuchElementException
This exception propogates to FluentWait class
Wherein
try {
V value = isTrue.apply(input);
if (value != null && (Boolean.class != value.getClass() || Boolean.TRUE.equals(value))) {
return value;
}
// Clear the last exception; if another retry or timeout exception would
// be caused by a false or null value, the last exception is not the
// cause of the timeout.
lastException = null;
} catch (Throwable e) {
lastException = propagateIfNotIgnored(e);
}
The exception is caught by Throwable, and this causes the timeout and I am not able to check whether all elements have been disappeared from the screen
P.S.
All my Elements are defined by #FindBy
Example
#FindBy(css = ".myclass-name")
private WebElement myWorkspaceButton;
So cannot use ExpectedConditions method taking By as argument
Is there any other way to check if all the WebElements have disappeared from the screen?
Or
Is there a solution to this problem?
You could write you own method for that in which you loop through all you elements and catch those exceptions.
public static ExpectedCondition<Boolean> invisibilityOfAllElements(
final List<WebElement> elements) {
return new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver webDriver) {
for (WebElement element : elements) {
try {
if (element.isDisplayed()) {
return false;
}
} catch (StaleElementReferenceException | NoSuchElementException ex) {
// ignore
}
}
return true;
}
#Override
public String toString() {
return "invisibility of all elements " + elements;
}
};
}
I am not sure but probably you need to catch org.openqa.selenium.TimeoutException as well.
Selenium's check for visibility/invisibility assumes that elements are present in DOM so the options are in:
Add another Explicit Wait to hold on until all the elements matching the locator query are absent like:
new WebDriverWait(driver,10).until(ExpectedConditions.numberOfElementsToBeLessThan(By.your_locator("your_query"),1));
You can supress the exception by providing the relevant ignoring stanza like:
new WebDriverWait(driver, 10)
.ignoring(NoSuchElementException.class)
.until(ExpectedConditions.invisibilityOfAllElements(elements));
More information:
WebDriver Advanced Usage: Explicit Waits
How to use Selenium to test web applications using AJAX technology

NullPointerException using WebDriverWait Boolean

I have two classes, one that runs the methods to click on buttons etc. On the page, there is a button that is disabled and I have a WebDriverWait to wait for it to be enabled again by checking that the attribute "disabled" has been removed from the html element. However, when I run the test I get a nullPointerException. I think I know where it's coming from but having a problem trying to work a way around it.
This is the method that runs to get to perform the actions:
public void methodThatRuns(WebDriver driver) throws InterruptedException {
properties.inputTxt(driver, "100");
sundries.waitEnabledButton(driver, properties.nextButton(driver));
properties.nextButton(driver).click();
}
This is the waitEnabledButton method from another class that it calls to wait:
public void waitEnabledButton(WebDriver driver, final WebElement btn) throws NullPointerException {
WebDriverWait wait = new WebDriverWait(driver, 10);
System.out.println("Starting the wait");
try {
wait.until(new ExpectedCondition<Boolean>(){
public Boolean apply(WebDriver driver) {
final String attribute = btn.getAttribute("disabled");
if (attribute.equals(null)) {
return true;
}
else {
return false;
}
}
});
} catch (StaleElementReferenceException e) {
System.out.println("The disabled attribute was destroyed successfully and the script can continue."); //using this as the attribute gets destroyed when the button is enabled which throws a staleElement exception
}
System.out.println("Wait is over");
}
Any help on this would be greatly appreciated!
if (attribute.equals(null)) {
return true;
}`
If attribute is null then .equals call will lead to NPE. Try with attribute == null.

SELENIUM Unable to close new tab

i been working on the selenium driver which i have to close the new tab else the current Testcase will fail due unable to allocate the directory of xpath. I notice that im calling 3 times of the webdriver , can anyone guide me through the mistake i made? Kindly advise . Thanks you in advance
SignIn_Action:
public class SignIn_ActionBuilder {
static WebDriver wd = new FirefoxDriver();
public static void Execute(WebDriver driver) throws Exception{
wd.get(Constant.URL);
wd.manage().window().maximize();
wd.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
Home_Page.Skip_Advertising(wd).click();
Home_Page.lnk_MyAccount(wd).click();
LogIn_Page.txtbx_UserName(wd).sendKeys(Constant.Username);
LogIn_Page.txtbx_Password(wd).sendKeys(Constant.Password);
wd.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
LogIn_Page.btn_LogIn(wd).click();
wd.manage().timeouts().implicitlyWait(120, TimeUnit.SECONDS);
}
}
Product Selection :
public class ProductSelectionConfirmation_Action {
static WebDriver wd = new FirefoxDriver();
public static void ThreeDigit_Execute(WebDriver driver) throws Exception{
// This is to get the Product name on the Confirmation page with using getText()/click method
// Once some text is stored in this variable can be used later in any other class
wd.manage().wait(120);
wd.close();
ConfirmationPlaceBet_Page.pick_PickLotteryNum1(wd).click();
ConfirmationPlaceBet_Page.pick_PickLotteryNum2(wd).click();
ConfirmationPlaceBet_Page.pick_PickLotteryNum3(wd).click();
ConfirmationPlaceBet_Page.btn_ConfirmNumberToBet(wd).click();
for (int i = 0; i < 49; i++) {
ConfirmationPlaceBet_Page.btn_IncreaseBet(wd).click();
}
ConfirmationPlaceBet_Page.btn_ProceedBet(wd).click();
ConfirmationPlaceBet_Page.btn_ConfirmBet(wd).click();
// This is all about Verification checks, these does not stop your execution but simply report fail at the end
// This is to check that if the value in the variable pick_PickLotteryNum1 is not null, then do this
}
}
TestCase :
public class Sobet_WBG_YiWanCai {
public WebDriver driver;
#Test(description = "WBG亿万彩 - 后三码" , enabled = true)
public void f() throws Exception {
try{
SignIn_ActionBuilder.Execute(driver);
ProductSelectionConfirmation_Action.ThreeDigit_Execute(driver);
Home_Page.lnk_LogOut(driver);
Home_Page.btn_LogOutDialog(driver);
driver.close();
}catch (Exception e){
Log.error(e.getMessage());
throw (e);
}
}
}
I can see a series of issues with the code you have posted.
In each of the Action classes you are creating a new static web driver object.
static WebDriver wd = new FirefoxDriver();
Which means it will open a new Firefox browser when the class is called.
And also you are passing a webdriver object in to the execute methods from the test case. But the passed webdriver is never used in the execute methods.
public static void ThreeDigit_Execute(WebDriver driver) throws Exception{}
You are not using the driver object for any action in the method but uses the wd object throughout the method.
Corrected code for the first class execute method :
public class SignIn_ActionBuilder {
public static void Execute(WebDriver driver) throws Exception{
driver.get(Constant.URL);
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
Home_Page.Skip_Advertising(driver).click();
Home_Page.lnk_MyAccount(driver).click();
LogIn_Page.txtbx_UserName(driver).sendKeys(Constant.Username);
LogIn_Page.txtbx_Password(driver).sendKeys(Constant.Password);
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
LogIn_Page.btn_LogIn(driver).click();
driver.manage().timeouts().implicitlyWait(120, TimeUnit.SECONDS);
}
}
And from the test case you have to create a webdriver object and pass it into the execute methods.
public class Sobet_WBG_YiWanCai {
public WebDriver driver;
#Test(description = "WBG亿万彩 - 后三码" , enabled = true)
public void f() throws Exception {
try{
//Create the driver instance here.
driver = new FirefoxDriver();
SignIn_ActionBuilder.Execute(driver);
ProductSelectionConfirmation_Action.ThreeDigit_Execute(driver);
Home_Page.lnk_LogOut(driver);
Home_Page.btn_LogOutDialog(driver);
driver.close();
}catch (Exception e){
Log.error(e.getMessage());
throw (e);
}
}
}
And you have to remove the static WebDriver wd = new FirefoxDriver(); line from all your action classes.

Test design for taking screenshot with Selenium WebDriver on failed JUnit tests

I'm running into a strange JUnit and Selenium issue.
I want to write a screenshot taker that will take a screenshot on failed tests.
I define the screenshot taker class as:
public class SeleniumJUnitScreenshotTaker implements MethodRule
{
private WebDriver driverLocal;
public SeleniumJUnitScreenshotTaker(WebDriver driver)
{
driverLocal = driver;
}
public void takeScreenshot(String fileName)
{
try
{
new File("test-results/scrshots/").mkdirs(); // Make sure directory is there
FileOutputStream out = new FileOutputStream("test-results/scrshots/" + fileName + ".png");
out.write(((TakesScreenshot) driverLocal).getScreenshotAs(OutputType.BYTES));
out.close();
}
catch (Exception e)
{
// No need to crash the tests here
}
}
public Statement apply(final Statement statement, final FrameworkMethod frameworkMethod, final Object o)
{
return new Statement()
{
#Override
public void evaluate() throws Throwable
{
try
{
statement.evaluate();
}
catch (Throwable t)
{
takeScreenshot(frameworkMethod.getName());
throw t; // rethrow
}
}
};
}
I've a base test class where I setup the WebDriver as follows:
public class TestBase
{
protected static WebDriver driver;
#Rule
public SeleniumJUnitScreenshotTaker seleniumJUnitScreenshotTaker = new SeleniumJUnitScreenshotTaker(driver);
.
.
.
#BeforeClass
public static void intialize()
{
.
.
driver = SeleniumWebDriverFactory.getWebDriver(browser.toString());
if ((browser != Browser.Chrome) && (browser != Browser.ChromeCanary))
{
driver.manage().window().maximize();
}
hostUrl = Configuration.getHostUrl(envUnderTest);
// Open Browser and navigate to main page
driver.navigate().to(hostUrl);
}
#Before
protected void setup() throws Exception
{
this.users = getUsers();
}
#After
protected void teardown()
{
this.testCases.cleanupChecks();
}
#AfterClass
public static void terminate()
{
// Shut down WebDriver
if (driver != null)
driver.quit();
SeleniumWebDriverFactory.stopDriverService();
}
}
The problem is when I try to run a series of tests in the test class (derived from TestBase), the tests after the first failure throws TimeoutException. This is because we don't close the current browser between tests and the new test tries to find things that are absent in current browser.
Is there a way to close browser in between tests but not close the driver? Or reinstantiate the driver between tests? Else is there an alt. design that can make this work?
Thanks
Yana

Best way to check that element is not present using Selenium WebDriver with java

Im trying the code below but it seems it does not work... Can someone show me the best way to do this?
public void verifyThatCommentDeleted(final String text) throws Exception {
new WebDriverWait(driver, 5).until(new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver input) {
try {
input.findElement(By.xpath(String.format(
Locators.CHECK_TEXT_IN_FIRST_STATUS_BOX, text)));
return false;
} catch (NoSuchElementException e) {
return true;
}
}
});
}
Instead of doing findElement, do findElements and check the length of the returned elements is 0. This is how I'm doing using WebdriverJS and I expect the same will work in Java
i usually couple of methods (in pair) for verification whether element is present or not:
public boolean isElementPresent(By locatorKey) {
try {
driver.findElement(locatorKey);
return true;
} catch (org.openqa.selenium.NoSuchElementException e) {
return false;
}
}
public boolean isElementVisible(String cssLocator){
return driver.findElement(By.cssSelector(cssLocator)).isDisplayed();
}
Note that sometimes selenium can find elements in DOM but they can be invisible, consequently selenium will not be able to interact with them. So in this case method checking for visibility helps.
If you want to wait for the element until it appears the best solution i found is to use fluent wait:
public WebElement fluentWait(final By locator){
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
});
return foo;
};
Hope this helps)
Use findElements instead of findElement.
findElements will return an empty list if no matching elements are found instead of an exception. Also, we can make sure that the element is present or not.
Ex: List elements = driver.findElements(By.yourlocatorstrategy);
if(elements.size()>0){
do this..
} else {
do that..
}
Unable to comment to The Meteor Test Manual, since I have no rep, but I wanted to provide an example that took me quite awhile to figure out:
Assert.assertEquals(0, wd.findElements(By.locator("locator")).size());
This assertion verifies that there are no matching elements in the DOM and returns the value of Zero, so the assertion passes when the element is not present. Also it would fail if it was present.
public boolean isDisplayed(WebElement element) {
try {
return element.isDisplayed();
} catch (NoSuchElementException e) {
return false;
}
}
If you wan t to check that element is displayed on the page your check should be:
if(isDisplayed(yourElement){
...
}
else{
...
}
int i=1;
while (true) {
WebElementdisplay=driver.findElement(By.id("__bar"+i+"-btnGo"));
System.out.println(display);
if (display.isDisplayed()==true)
{
System.out.println("inside if statement"+i);
driver.findElement(By.id("__bar"+i+"-btnGo")).click();
break;
}
else
{
System.out.println("inside else statement"+ i);
i=i+1;
}
}
WebElement element = driver.findElement(locator);
Assert.assertNull(element);
The above assertion will pass if element is not present.
In Python for assertion I use:
assert len(driver.find_elements_by_css_selector("your_css_selector")) == 0
My answer is much more simpler and it works for me
while(true) {
if (driver.getPageSource().contains("Enter the text of the element you wanted to check")==false)
{//Put your code here
break;
}
else if (isElementPresent(element you are trying to find)==true)
{
//put your code here
break;
}
}
WebElement element = driver.findElement(locator);
Assert.assertFalse(element.isDisplayed());
The assertion will pass if the element is not present, otherwise it will fail.

Categories