How to use Page Objects in this scenario?



  • I have a website with a home page that requires a user to be authorized or logged in to see all pages of the website. If you try to access the home page, but you are not logged in, then the website sends you to a login page. The url of the page has two query parameters - some id to identify the client and the referring url. Once you login, you get access to the homepage. If you are on a page called pageABC and your session gets timed out, then you'll be shown the login page. You will go back to the previous page after logging in.

    How do I model this scenario in terms of page objects?

    I already have a HomePageObj which has a webdriver instance. It also has a void get() method which opens the homepage url. Should I model that page in one of the following ways or try something else ?

    1 - Change void get() to return a LoginPageObj if user is redirected to login page, else return null? Then, my tests can do a login if they get null.

    2 - Add a member variable called User to each page object. If void get() redirects to login page url, then use the credentials in User object to automatically do the login and open the desired url?

    3 - Should I have a BasePageObj with a void get() method which works in way I mentioned in point 2? Then, all pages will extend this BasePageObj.

    UPDATES :

    Regarding point 3 - BasePageObj can have two variables "requiresLogin" & "doAutoLogin". If requiresLogin = true & doAutoLogin = true, then do the login automatically. Any flaws in this approach ?

    Thanks.



  • When I think how to design a test framework I always ask myself if the code I am writing would be easy to understand by someone else in 6 months. That is why I would suggest to keep it as simple as possible.

    Since we are talking about a small amount of test cases that will deal with the timeout, you can implement timeout specifc functions inside coresponding page objects. So lets say you have a class called SomePage, you would do something like this:

    public SomePage timeoutAndLogin(User user) {
        waitTillTimeout();
        new LoginPage(driver).login(user);
        return this;
        }
    

    This way your page objects still model the behaviour of real page, you easly get back a reference to SomePage object and can utilize method chaining.

    Edit

    If you want a solution that will take care of login on every page, you would have to do something similar to what you mentioned in points 2 & 3. But instead of writing a void get() each page object could have a default constructor like this:

    public SomePage(WebDriver driver, User user) {
        if(driver.getCurrentUrl() == LOGIN) {
            new LoginPage(driver, user).login();
        };
        this.user = user;
        this.driver = driver;
    } 
    

    So before a page is returned, we check if the URL points to login page and login back if it did (if your URL does not change, something else can be used i.e. WebElement or title).

    Bare in mind that this solution can result in false positive test results, as any scenario in which a timeout should not happen and it does, will take care of the login and ignore the failure. It also adds an extra variable to each page (User) and restricts you to the same user.

    The previous option would probably fail for different user, but for specific scenario a different function can be created:

    public LoginPage timeoutAndLoginDifferentUser(User user) {
        waitTillTimeout();
        new LoginPage(driver).login(user);
        return new LoginPage(driver);
    }
    

    Post update edit

    Any kind of boolean flag adds additional complexity layer. Two flags mean your code can end up in one of four possible states. This can lead to a lot of frustration for any person that will have to use the framework in the future, as debugging will become a pain. I had to work with Ruby Cucumber framework that used flags together with some kind of global variables - code was executing either in a nested iframe or in a new tab. It lead to lots of hours lost on debugging why we are receiving NoSuchElementException when everything seemed fine.



Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2