Selenium WebDriver – How To Handle Annoying Random Popup / Alerts

Overview:

In this article, Lets see how we could handle random popups / alerts / ads / some unexpected conditions & how we could recover from that.

Udemy – Java 8 and Beyond for Testers:

TestAutomationGuru has released a brand new course in Udemy on Java 8 and Beyond for Testers. 12 hours course with java latest features, lambda, stream, functional style programming etc. Please access the above link which gives you the special discount.  You can also get your money back if you do not like the course within 30 days.

Problem Statement:

I had an application which used to show popups / ads, as shown below, at random. As per the requirement it can be shown anytime (there was some complex business rules behind that. but lets ignore that for the time being). The user had to either click on the close button or take some action on the popup before continuing. It would make our selenium tests fail as this popup will steal the focus. It would be annoying for us – but it was generating some revenue for our organization!!

ele-proxy-002

While automating this application, We wanted to have our selenium scripts to be something like this…

doSomethingA();
doSomethingB();
doSomethingC();

But our selenium scripts used to be something like this.

public void checkForPopupAndKill(){
    if(popup.isDisplayed()){
        popup.close();
    }
}

checkForPopupAndKill();
doSomethingA();
checkForPopupAndKill();
doSomethingB();
checkForPopupAndKill();
doSomethingC();

The team had to include checkForPopupAndKill before each and every statement to handle the popup. As you see,the script looked horrible!!  This is because the source/client (here it is our selenium scripts) is directly interacting with the target object (actual application). As the popup can be shown anytime in the application, it would steal the focus when it appears. So , say, any click even on the main application can not be done as it would throw an exception that ‘Other element would receive the click’. So, we could not escape from adding checkForPopupAndKill  for every statement as per this approach.

ele-proxy-003

 

I was looking for something like an intermediary object between the source and target and let the intermediary object handle this popup. So that your selenium scripts do not have to worry about killing the popup.

ele-proxy-004

If we could use an intermediary  object – we could write statements as we wanted to have as shown below. All these statement do not get executed directly on the target object. Instead the intermediary object decides what to do!

doSomethingA();
doSomethingB();
doSomethingC();

Java Dynamic Proxy:

Java supports the creation of dynamic proxy classes and instances. Proxy objects are useful in many situations to act as an intermediary between a client object and a target object. We could create a proxy object by implementing InvocationHandler interface.

Lets create an ElementProxy class which implements this interface. Basically, the proxy’s invoke method would be called first before the actual method is invoked. As our idea was to call checkForPopupAndKill before invoking any action on a WebElement, this could be the right place to include the checkForPopupAndKill method.

public class ElementProxy implements InvocationHandler {

    private final WebElement element;

    public ElementProxy(WebElement element) {
        this.element = element;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //before invoking actual method check for the popup
        this.checkForPopupAndKill();
        //at this point, popup would have been closed if it had appeared. element action can be called safely now.
        Object result = method.invoke(element, args);
        return result;
    }

    private void checkForPopupAndKill() {
        if (popup.isDisplayed()) {
            System.out.println("You damn popup, you appearded again!!?? I am gonna kill you now!!");
            popup.close();
        }
    }
    
}

We need to wrap our regular WebElement with this proxy object. We basically need a class which has a method to accept a WebElement and returns the WebElement with some wrapper.

public class ElementGuard {

    public static WebElement guard(WebElement element) {
        ElementProxy proxy = new ElementProxy(element);
        WebElement wrappdElement = (WebElement) Proxy.newProxyInstance(ElementProxy.class.getClassLoader(),
                                                                       new Class[] { WebElement.class },
                                                                       proxy);
        return wrappdElement;
    }

}

When we call the below statement, it creates wrapper around element and returns the element.

ElementGuard.guard(element)

ele-proxy-005

If we try to call the click method of the WebElement, it would always call the ‘invoke’ method first, then it would call the ‘click’

ele-proxy-006

 

I create the below class to init elements of the page object with wrapper elements.

public class MyPageFactory {
    
    public static <T> void initElements(WebDriver driver, T pageobject){
        
        //first init elements
        PageFactory.initElements(driver, pageobject);
        
        //then access all the WebElements and create a wrapper
        for(Field f:pageobject.getClass().getDeclaredFields()){
            if(f.getType().equals(WebElement.class)){
                boolean accessible = f.isAccessible();
                f.setAccessible(true);
                //reset the webelement with proxy object
                f.set(pageobject, ElementGuard.guard((WebElement) f.get(pageobject)));
                f.setAccessible(accessible);
            }  
        }

    }
    
}

My sample page would be something like this – without much change.

public class RegistrationPage {

    private final WebDriver driver;

    @FindBy(name = "firstName")
    private WebElement firstName;

    @FindBy(name = "lastName")
    private WebElement lastName;

    @FindBy(name = "email")
    private WebElement userName;

    @FindBy(name = "password")
    private WebElement password;

    @FindBy(name = "confirmPassword")
    private WebElement confirmPassword;

    @FindBy(name = "register")
    private WebElement submit;

    public RegistrationPage(WebDriver driver) throws Exception {
        this.driver = driver;
        MyPageFactory.initElements(driver, this);
    }

    public RegistrationPage launch() {
        driver.get("http://newtours.demoaut.com/mercuryregister.php");
        return this;
    }

    public RegistrationPage setFirstName(String firstName) {
        this.firstName.sendKeys(firstName);
        return this;
    }

    public RegistrationPage setLastName(String lastName) {
        this.lastName.sendKeys(lastName);
        return this;
    }

    public RegistrationPage setUserName(String userName) {
        this.userName.sendKeys(userName);
        return this;
    }

    public RegistrationPage setPassword(String password) {
        this.password.sendKeys(password);
        return this;
    }

    public RegistrationPage setConfirmPassword(String confirmPassword) {
        this.confirmPassword.sendKeys(confirmPassword);
        return this;
    }

    public void submit() {
        this.submit.click();
    }

}

My tests would be something like this.

RegistrationPage r = new RegistrationPage(driver);

r.launch()
 .setFirstName("fn")
 .setLastName("ln")
 .setUserName("un")
 .setPassword("password")
 .setConfirmPassword("password");

When I execute the tests, all the popup checks happens behind the scenes.

going to call :sendKeys with args : fn
going to call :sendKeys with args : ln
You damn popup, you appearded again!!?? I am gonna kill you now!!
going to call :sendKeys with args : un
going to call :sendKeys with args : password
going to call :sendKeys with args : password

Summary:

By using Dynamic Proxy object,  all the unexpected events like this can he handled behind the scenes. Our page object and tests look exactly the same. But any action goes via the proxy object. I do not have to repeat the checkForPopupAndKill method every time. proxy object takes care of it!  Not only this popup or alert, any logging, reporting etc can be handled like this.

 

Happy Testing & Subscribe 🙂

 

Share This:

27 thoughts on “Selenium WebDriver – How To Handle Annoying Random Popup / Alerts

    1. I assume you meant the driver instance inside the ElementProxy class. It can be passed to the ElementProxy through ElementGuard in MyPageFactory class. Once you have the driver instance, you could look for the popup. However I use a different approach in my framework. I have a util class which has a static method which is responsible for returning driver instance stored in threadlocal.

      1. Hey

        Very cool approach, can you suggest something ?
        If we can add fluent wait in Invoke method ? And wait for each web element to appear ?

          1. Yes Implicit wait does that but project wants to build a safety check for element existence? So I was thinking of adding an assert with ExpectedConditions for a max wait time for each element before invoke, what this will do is that before any element it will assert that element is enabled and displayed if not assert will fail

  1. popup.isDisplayed(): what is popup here? when I used this code it’s asking me to create a local variable ‘popup’. If so what value I should assign to it?

    1. popup is the annoying object you want to deal with! instead of popup, you can use, driver.findElement(By.id(‘locator for popup’)).isDisplayed()

  2. Nice article. I try to use this way to do test. Now I have a question. I use the actions class : Actions action = new Actions(driver);
    action.moveToElement(AccountMenuBtn).perform();
    It throws the error:
    java.lang.ClassCastException: com.sun.proxy.$Proxy19 cannot be cast to org.openqa.selenium.interactions.internal.Locatable
    at org.openqa.selenium.interactions.Actions.moveToElement(Actions.java:387). I don’t know if action doesn’t work on wrapped element .

    1. Joan, Action.moveToElement expects a WebElement. Wrapped Element is also a WebElement. it should work without any issues. Please try to use a stable version of selenium lib and ensure that it works fine without dynamic proxy. then you can move on to dynamic proxy.

  3. Does this method create any extra running time? If it runs for every driver command then the overall execution time will be affected? how much difference did you get?

    1. Reflection will have impact on the performance theoretically. In reality , it is negligible. You can measure it.

  4. Very nice approach…..
    My doubt is….
    How is that myPageFactory class methods ate called?????

  5. Sorry sir….
    Initially I didn’t get it…..
    I got it where it is called from….
    Plz ignore….

  6. We are facing issues while trying to use the code mentioned. Self Invoke is not getting called. Please help.

    1. It should be invoked or We could do something wrong. You need to provide your sample code etc. You better ask this question in Stackoverflow.com – I am saying this because you would get immediate help. More info you provide more easy for you to get the answer quickly.

  7. “However I use a different approach in my framework. I have a util class which has a static method which is responsible for returning driver instance stored in threadlocal.” => Do you have sample code related to this? Tried already but still got some errors from my project

    1. The above is the ‘worked code’ for me. There are N number of ways to solve a problem. So use whatever works for you.

  8. Thank for the approach, a wonderful idea. I have a quick question ? If we implement an explicit wait in the custom class ? Do you think this will work as a default explicit wait for all web elements in page factory, I am thinking about doing this ? Just wanted to get your thoughts on the same

  9. Thanks for such a nice approach, could you advice from where you’re getting the popup WebElement element inside checkForPopupAndKill method

    private void checkForPopupAndKill() {
    if (popup.isDisplayed()) {
    System.out.println(“You damn popup, you appearded again!!?? I am gonna kill you now!!”);
    popup.close();
    }
    }

    1. Hi,
      There are various ways to implement that. I was following a dependency injection approach with spring boot. So I did not want to cover this here. But take a look at MyPageFactory You have driver instance. Pass that to ElementGuard.guard and take decision there if the popup is displayed.

  10. Hello, I came across your article and found it helpful. But we have been using TypeScript with Cucumber and WebDriverIO. Can we apply the same to the framework we are using.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.