Code & QA

WebElement

Let’s get back to WebElement class created previously as a stub for IClickableElement interface. WebElement is the central entity of the framework.

This is base class for all classes which represent web elements used in the tested application. At the moment the class has no members – it’s just a stub – but the time to fill it with some stuff has come.

The class contains:

· A set of constructors. All the constructors receive IWebDriver instance as a parameter. It is the very instance initialized in WebApplication class and passed to a web page class. One of the constructors has parametrized input of element locators. Parametrized means that you have the ability to pass an array of locators, which will be used for searching the element, as a single value or as an array of values or as a number of values separated by comma or you can pass nothing instead. In either case the code will be compiled and will work properly. For example, if a constructor is looking like

public WebElement(IWebDriver driver, By[] locator) {}

then you must invoke it in only the following way:

WebElement element = new WebElement(driver, new By[] { By.ClassName(“profile-img”) });

The locator parameter in the example is compulsory and must be passed only as an array even if it has only single value.

When you add params word to the constructor

public WebElement(IWebDriver driver, params By[] locator) {}

it may be invoked like

WebElement element = new WebElement(driver, new By[] { By.ClassName(“profile-img”)}));//an array, the same as in previous example

WebElement element = new WebElement(driver, By.ClassName(“profile-img”) );//single value

WebElement element = new WebElement(driver, By.ClassName(“profile-img”), By.Id(“signIn”) );//comma separated multiple values

WebElement element = new WebElement(driver);//no parameter

The last case may cause run-time error. If no locator is passed the element will never be found on a page. Do not forget to catch possible exceptions or provide the logic for finding the element with locator by default or without it.

· Instances of IWebDriver and IWebElement interfaces.

Inner field of IWebDriver type is used for interaction with the element and auxiliary actions such as taking screenshots.

IWebElement – an instance of origin web element;

· Properties and methods declared inside inherited classes and implemented interfaces – WebElement and IClickableElement – Name, IsFound, IsDisplayed, IsEnabled, Click(), DragNDrop(), etc.

using System;

using Logger;

using OpenQA.Selenium;

namespace Mapping.WebElements

{

public abstract class WebElement

{

private WebElement(IWebDriver driver, string name)

{

Name = name;

Driver = driver;

}

protected WebElement(IWebDriver driver, string name, IWebElement element) : this(driver, name)

{

Element = element;

}

protected WebElement(IWebDriver driver, string name, int? waitTimeout = null, params ElementLocator[] locators) : this(driver, name)

{

string elementName = string.IsNullOrEmpty(name) ? string.Empty : name;

if (locators == null || locators.Length == 0)

Report.AddWarning(“Finding IWebElement inside web element constructor”, “At least one locator must be passed to element constructor”, “No locator for ” + GetType() + ” ” + elementName + ” element specified”);

else

{

Element = driver.GetWebElement(GetType(), elementName, waitTimeout, locators);

}

}

protected IWebDriver Driver;

internal protected IWebElement Element { get; set; }

internal protected Frame[] Frames { get; set; }

public string Name { get; set; }

public virtual bool IsEnabled

{

get

{

try

{

if (Element != null)

return Element.Enabled;

}

catch (Exception ex)

{

Report.AddWarning(“Getting IsEnabled property”, “IsEnabled property returns true if element is available for interaction or false if it is read-only”, ex.Message, Driver.TakeScreenshot(“Getting IsEnabled property”));

}

return false;

}

}

public bool IsDisplayed

{

get

{

try

{

if (Element != null)

return Element.Displayed;

}

catch (Exception ex)

{

Report.AddWarning(“Getting IsDisplayed property”, “IsDisplayed property returns true if element is displayed on page or false if it is hidden or is out of work area”, ex.Message, Driver.TakeScreenshot(“Getting IsEnabled property”));

}

return false;

}

}

public bool IsFound

{

get

{

try

{

if (Element != null)

{

var p = Element.Location;

return true;

}

}

catch (Exception ex)

{

Report.AddWarning(“Getting IsFound property”, “IsFound property returns true if element is found in DOM structure of page or false if it is not found”, ex.Message, Driver.TakeScreenshot(“Getting IsEnabled property”));

}

return false;

}

}

}

}

Notice that one of the constructors take as a parameter instance of the ElementLocator class. This is a class which consists of Frames array (I assume that this is a sequence of iframes inside which the driver must be switched to reach correct document before starting looking for targeted web element) and OpenQA.Selenium.By class instance – element’s locator. If searched element in located not in an iframe the Frames parameter may be ignored, otherwise it must be passed as sequence of locators of iframes.

ElementLocator elLocator = new ElementLocator(By.ClassName(“myElementClass”));

ElementLocator elInFrameLocator = new ElementLocator(new object[] { “frame_id”, 1, By.XPath(“//div[@id=’div_id’]/div[1]/iframe”) }, By.ClassName(“myElementClass”));

elLocator is equal just to By.ClassName(“myElementClass”). elInFrameLocator consists not only of By.ClassName(“myElementClass”) but of the array of objects as well. Values of the array will be used for switching to necessary iframe before starting searching of an element. In this case driver must be switched into iframe with id equal to ‘frame_id’ then it should be switched to the second iframe element found inside the ‘frame_id’ iframe, and afterwards, it must be switched on the third level of depth into the iframe by specified XPath. All the actions are performed in GetWebElement() method which I create as ISearchContext instance extension. If the application under test does not contain iframes there is no need to use ElementLocator class. It may be easily replaced with native Selenium By class.

GetWebElement() searches targeted web element on a page. It takes as input parameter an instance of ISearchContext interface. This may be either an instance of IWebDriver or IWebElement as they both implement ISearchContext. If ISearchContext is IWebDriver the targeted element will be searching over the entire page, otherwise, if ISearchContext is IWebElement, the targeted element will be sought only among child nodes of the IWebElement. Also it takes as a parameter an ElementLocator class instance (described above) and invokes SwitchToFrame() method (described below).

I put class ElementLocator in the Interfaces.cs file. You can put it in separate file or follow my manner.

public class ElementLocator

{

internal object[] Frames;

internal By Locator;

internal ElementLocator(By locator)

{

Locator = locator;

}

internal ElementLocator(object[] frames, By locator) : this(locator)

{

Frames = frames;

}

}

Please keep in mind that there is still an error in the code which does not allow compiling the project. It is presence of GetWebElement() method in WebElement constructor. To avoid errors let me create a stub for the method. It must be put in Extensions class since it is an extension method for IWebDriver.

/// <summary>

/// Finds web element on a page

/// </summary>

/// <param name=”driver”>instance of IWebDriver or IWebElement</param>

/// <param name=”elementType”>type of class the targeted element is wrapped in. E.g.: Button, Link, Textbox, etc.</param>

/// <param name=”elementName”>name of targeted web element</param>

/// <param name=”waitTimeout”>time in seconds for waiting targeted element is loaded and is present on a page</param>

/// <param name=”locators”>targeted element locators</param>

/// <returns>an instance of IWebElement or null if the element is not found</returns>

public static IWebElement GetWebElement(this IwebDriver driver, Type elementType = null, string elementName = null, int? waitTimeout = null, params ElementLocator[] locators)

{

return null;

}

[row]
[column lg=”4″ md=”12″ sm=”12″ xs=”12″ ]
Switching between tabs/windows and frames [/column]
[column lg=”4″ md=”12″ sm=”12″ xs=”12″ ]
Table Of Content
[/column]
[column lg=”4″ md=”12″ sm=”12″ xs=”12″ ]
More extension methods
[/column]
[/row]

Leave a Reply