Code & QA

Adding a page to the application. Method Open()

After a page class is created it must be added to the Application class for easier usage in tests. Every page, which the application consists of, is separate property of the WebApplication class. It allows not to calculate all the pages initially when a test starts but to calculate it only during invocation. Initiation of a page instance is provided automatically behind the scene though there is still the possibility to create an instance of a page explicitly for specific cases.

Since a page is declared as property it is invoked every time when it’s referenced. But when I work with a number of elements on the same page I do not want the page being recalculated every time I use an element (and refer to the page). So I added a logic which allows avoiding page recalculation if the page is already initialized and still is valid (simple Singleton development pattern).

For the purpose I added a private variable of HomePage type and a public property of the same type to WebApplication class:

using Logger;

using Mapping.TestingWithSelenium;

using OpenQA.Selenium;

using System.Configuration;

namespace Mapping

{

/// <summary>

/// projection of an application under testing

/// </summary>

public class WebApplication

{

internal IWebDriver Driver { get; private set; }

public WebApplication(IWebDriver driver)

{

this.Driver = driver;

_isNew = true;

}

bool _isNew;

internal static bool IsValid;

#region Pages

private HomePage _homePage;

public HomePage HomePage

{

get

{

if (_isNew)

Open<HomePage>();

if (!IsValid || _homePage == null)

{

_homePage = new HomePage(Driver) { Name = “Home” };

//Actually the variable must be set True, but if a page contains frames it may cause problems because some elements of a page may be located in a frame and others may be out. If you refer to an element out of the frame, then refer to an element inside it, you’ll get StaleElementReferenceException referring again to outer element. It occurs because the driver is switched inside the frame and everything out of it is not available any more. When IsValid is False it forces recalculating an element every time it is referred to.

IsValid = false;

}

return _homePage;

}

}

#endregion Pages

/// <summary>

/// Initializes an instance of specified web page

/// </summary>

/// <typeparam name=”T”>type of web page for initialization</typeparam>

/// <param name=”args”></param>

public void Open<T>(params object[] args) where T : IWebPage

{

_isNew = false;

if (typeof(T) == typeof(HomePage))

{

Report.AddInfo(“Navigating Home page”);

Driver.Navigate().GoToUrl(Globals.applicationURL);

}

}

/// <summary>

/// closes the application (browser)

/// </summary>

public void Quit()

{

Driver.Quit();

_isNew = true;

}

}

}

There are also two interesting variables bool _isNew and property bool IsValid that are used inside HomePage property. _isNew is instantiated as True in the class constructor, i.e. when the application starts (new browser is launched). The flag indicates that at the moment when the application is started there is no pages loaded yet and any of a page initialized will be new. Therefore any page on this stage must be initialized with Open<T>() method. Then, the flag will be changed to False inside Open<T>() method once and for all the WebApplication class life circle.

Hence inside HomePage property the Open<T>() method is invoked only if _isNew variable is True. The method knows how to load and instantiate any required page (actually how to open it in a browser) and do necessary actions for this (for example, navigates to a page by URL-address, or clicks appropriate elements on current page, or performs a sequence of actions required for page loading).

Then _homePage variable is returned. Of course in case only if it is instantiated already and if another flag IsValid is equal to True. Otherwise, HomePage constructor will be invoked and _homePage variable is (re)initialized.

IsValid flag indicates that currently opened page is still valid and the driver can interact with its elements. Considered it helps to avoid getting StaleElementReferenceException. If the page has been reloaded or closed or changed in a way that some of its elements are not available for interaction the IsValid variable must be set to False. I do not recommend set the variable to True for pages which contains frames (see comment to the code above).

Thus, HomePage property always returns actual version of HomePage class.

Now let’s look onto Open<T>() method. First, the method sets _isNew variable to false indicating that a page is being loaded in browser. Then it verifies T parameter – T is type of a page to be loaded – and if it is equal to HomePage, the driver performs appropriate actions.

Leave a Reply