Skip to content

PageObject with new controls

peterrexj edited this page Apr 29, 2024 · 12 revisions

Page Object Model

Page Object Model is a design pattern to create an Object Repository for web UI elements. Under this model, for each web page in the application, there should be a corresponding page class. This Page class will find the WebElements of that web page and also contains Page methods which perform operations on those WebElements.

Please read through the Page Object Model and its advantages of using in Test Automation.

IWebElement

Web Elements or which is called IWebElement is the default type which represents an element in the Page. With IWebElements, you need to write methods to perform special operations against the different type of elements, for example, to check a checkbox or upload a file.

To overcome some of the usual problems, the new controls clearly differentiates the type of element used in a page and encapsulate its required functionality.

New Controls

The below is the list of controls available and that can be mapped to what you see in the web page.

Every control inherits from the BaseControl, which means, every control will have all the properties of the base control and it has the definition for the common default functionality that an element requires. Here are some of them

Wait Operations

Wait operations are the most important aspect of Web or Mobile automation. Properly managing wait operations on the elements leads to the consistent execution of the automation scripts without failure. Try not to use Thread.Sleep(..) in your application and usage of Sleep(..) can be avoided by mixing wait operations in your script.

You can wait until an element goes invisible before you continue with the next operation. For example, clicking on a button which makes a ajax request that bring up spinner or wait control visible in the page, and now you can wait for that spinner control to go invisible before you continue with the next operation. Having Thread.Sleep(..) is a static wait and degrades your script performance.

Every control comes with the below default wait operation and returns bool if the condition was met.

Override default wait operations (optional)

waitTimeSec (int): Is the total amount of time to wait. By default, all wait operations wait against the default wait period set during the load (which can be changed on the test initialization) SeAppConfig.DefaultTimeoutWaitPeriodInSeconds . Override this parameter to wait for less or more time depending on your scenario. For example, you can wait for 2 seconds in certain operations and continue if you don’t find or you can wait for 180 seconds on a spinner to go invisible which takes more time during submit operations.

throwExceptionWhenNotFound (bool): Determines whether to throw an exception if the condition was not met during the waiting process and the default is set to true. For example, for a scenario, when you want to see if the element is visible and then click only if available by not throwing an exception if not found.

if (_element.WaitUntilElementVisible(waitTimeSec: 2, throwExceptionWhenNotFound: false)) {
	element.Click();
}

errorMessage (string): Custom message to throw when the wait operation fails to meet the condition. This can be used as an assertion for the wait operation and will help in debugging and is always a good practice to use the proper message for all your wait operations in the scripts.

_element.WaitUntilElementVisible(waitTimeSec: 10, errorMessage: “The Login button was not visible is the UI, make sure the element is displayed to proceed with the automation”);

The above line will throw an exception if the element is not visible, but instead of throwing the default error message from Selenium, you will get “The Login button was not visible is the UI, make sure the element is displayed to proceed with the automation” and will help in the investigating your script failure from the CI CD pipelines and make your life easier.

  1. RetryFindElement: This method attempts to find an element on the page, retrying a specified number of times if the element is not found. It throws an exception if the element is not found after all retries.
  2. RetryFindElements: Similar to RetryFindElement, but this method attempts to find multiple elements on the page.
  3. QuickFindElement: This method attempts to quickly find an element on the page, retrying a few times if the element is not found.
  4. Click: This method clicks on the element. If the element is disabled or does not exist, it throws an exception.
  5. DoubleClick: This method double-clicks on the element.
  6. WaitAndClick: This method waits for a specified amount of time and then clicks on the element.
  7. ScrollAndClick: This method scrolls to the element and then clicks on it.
  8. ClickByJsScript: This method clicks on the element using JavaScript.
  9. WaitClickTillElementGoesInvisible: This method waits for the element to be visible, clicks on it, and then waits until the element goes invisible.
  10. WaitClickAndIgnoreError: This method waits for the element to be visible and then clicks on it, ignoring any exceptions that occur.
  11. SendKeys: This method sends the specified text to the element.
  12. SendEnter: This method sends the Enter key to the element.
  13. SendTab: This method sends the Tab key to the element.
  14. ScrollTo: This method scrolls to the element.
  15. Clear: This method clears the content of the element.
  16. Highlight: This method highlights the element in the UI.
  17. SetFocusByJavascript: This method sets the focus to the element using JavaScript.
  18. ToString: This method returns a string representation of the element, including its type, selector, and description.

Each of these methods is virtual, meaning they can be overridden in derived classes to provide custom behavior.

  1. WaitUntilElementEnabled: This method waits until the element is enabled. It throws an exception if the condition is not met within the specified time.
  2. WaitUntilElementVisible: This method waits until the element is visible. It throws an exception if the condition is not met within the specified time.
  3. WaitUntilElementExists: This method waits until the element exists. It throws an exception if the condition is not met within the specified time.
  4. WaitUntilElementCssDisplayed: This method waits until the element is displayed according to CSS (i.e., display: none is not applied). It throws an exception if the condition is not met within the specified time.
  5. WaitUntilElementInvisible: This method waits until the element is not visible. It throws an exception if the condition is not met within the specified time.
  6. WaitUntilElementClickable: This method waits until the element is clickable. It throws an exception if the condition is not met within the specified time.
  7. WaitUntilElementTextTrimEquals: This method waits until the trimmed text of the element equals the specified text. It throws an exception if the condition is not met within the specified time.
  8. WaitUntilElementTextStartsWith: This method waits until the trimmed text of the element starts with the specified text. It throws an exception if the condition is not met within the specified time.
  9. WaitUntilElementTextContains: This method waits until the text of the element contains the specified text. It throws an exception if the condition is not met within the specified time.
  10. WaitUntilElementHasSomeText: This method waits until the element has some text. It throws an exception if the condition is not met within the specified time. Each of these methods has an overload that allows you to specify the total amount of time to wait (in seconds) to meet the condition. If the condition is not met within this time, the method will either return false or throw an exception, depending on the value of the throwExceptionWhenNotFound parameter.

Table Control

The TableControl class is a part of the Selenium.Essentials namespace and extends the BaseControl class. It's designed to provide a set of methods and properties to interact with HTML tables in a web page when using Selenium WebDriver for automated testing. Key features of the TableControl class include:

  • Loading and Waiting: It provides a WaitForTableLoadComplete method to wait until a table is fully loaded on a webpage. It also has a LoadWaitingSelector property to specify a loading spinner or similar element.
  • Row and Column Counting: It has properties like RowCount, ColumnCount, and TotalColumns to get the number of rows and columns in the table.
  • Cell and Row Access: It provides methods like Item, Row, and Click to interact with specific cells or rows in the table.
  • Column Name Mapping: It maintains a cache of column names and their positions in the table for quick access.
  • Data Extraction: It provides methods like GetColumnValues and GetRowPosition to extract data from the table.
  • Element Interaction: It provides methods like Click, ClickByText, Set to interact with elements in the table.
  • Header, Body, and Footer Access: It provides methods like GetHeaderControl, GetBodyControl, and GetFooterControl to interact with specific parts of the table. This class is a powerful tool for automating interactions with complex HTML tables during web testing.

The example below is from the website Wikipedia and using a page which has list of countries. The objective is to find the country "France" and click on the link (navigate) from a table on that page

Assumptions:

  • using Page Object Model and the page contains the Table control
  • the control is private and should have public methods to perform the operations (following page object model)
  • each operation(s) in the below example should be encapsulated into its own methods
  • this is the page used in the example https://en.wikipedia.org/wiki/List_of_sovereign_states
  • the below example is exposing the control directly out of the page and performing action directly on it, which should not be the case and this is just for demo purpose ONLY!
private TableControl _countryTable => new (_driver, By.CssSelector("table.sortable.wikitable.jquery-tablesorter"));
  • even though the above example shows private control, the below code works as it was converted to public, but please use private and appropriate methods for specific actions
//wait for the table to complete its loading and appear (can be overriden)
 WikiListPage._userTable.WaitForTableLoadComplete(); 

//get the list of column names
 var colNames = WikiListPage._userTable.ColumnNames; 

//find the position of the France with exact match is false, the reason being it has whitespaces before and after the text
 var francePosition = WikiListPage._userTable.GetRowPosition("Common and formal names", "France – French Republic", exactMatch: false); 

//one of the option to get a control on the France link using xapth
 var franceLink01 = WikiListPage._userTable.GetBodyControl<WebControl>("Common and formal names", francePosition, "//a"); 

//another option to get a control reference using any selector and in this case by tag name
 var franceLink02 = WikiListPage._userTable.Item(francePosition, "Common and formal names", By.TagName("a")); 

//another option to get the control
 var franceLink03 = WikiListPage._userTable.Item<Link>(francePosition, "Common and formal names", By.TagName("a")); 

//with any of the above option you perform other operations and in this case its waiting and clicking on the link
 franceLink01.WaitAndClick(); 

//click can also be performed as below
//directly performing action on the element within a table cell found by a tag name or using any custom selector
 WikiListPage._userTable.Click(francePosition, "Common and formal names", By.TagName("a")); 

CollectionControl

The CollectionControl class in the Selenium.Essentials namespace is a part of a Selenium WebDriver framework for automating browser actions. This class extends the BaseControl class and is used to interact with a collection of web elements on a webpage. Here's a brief summary of its key features:

  • Constructor: The class has multiple constructors that allow you to create a CollectionControl with different parameters. You can pass in a WebDriver instance, a selector (By), a parent control, a description, and flags for first available and excluding ID checks for XPath calculation. You can also pass in custom scroll actions.

  • TotalRaw and Total: These properties return the total number of elements matching the selector, including hidden ones. Total is kept for backward compatibility.

  • Item and VisibleItem: These methods return a control of a specified type at a given position in the UI. The VisibleItem method only considers visible elements.

  • FirstVisibleControl and FirstVisibleElement: These methods return the first visible control from the list.

  • Click, DoubleClick, Set, Get: These methods perform actions on the element at a given position. Click and DoubleClick perform click actions, Set sets a value to an element, and Get retrieves the value of an element.

  • FindPositionByText: This method finds the position of an element based on the text it contains.

  • WaitForMinimumOne, WaitForElementVisible, WaitForElementInvisible: These methods are used to wait until certain conditions are met. WaitForMinimumOne waits until at least one element appears, WaitForElementVisible waits until an element at a certain position is visible, and WaitForElementInvisible waits until an element at a certain position is removed from the UI. This class provides a convenient way to interact with collections of web elements in a Selenium WebDriver test, making it easier to write clean, readable tests.

  • CollectionControl (constructors): These are the constructors for creating a new instance of CollectionControl. They take in parameters like the WebDriver instance, the selector (By), a parent control, a description, and flags for first available and excluding ID checks for XPath calculation. You can also pass in custom scroll actions.

  • TotalRaw: This property returns the total number of elements matching the selector, including hidden ones.

  • Total: This property is kept for backward compatibility and also returns the total number of elements matching the selector.

  • Item: This method returns a control of a specified type at a given position in the UI.

  • VisibleItem: This method returns a control of a specified type at a given position in the UI, but only considers visible elements.

  • FirstVisibleControl: This method returns the first visible control from the list.

  • FirstVisibleElement: This method returns the first visible control from the list, specifically of type WebControl.

  • Click: This method performs a click action on the element at a given position.

  • DoubleClick: This method performs a double-click action on the element at a given position.

  • Set: This method sets a value to an element at a given position.

  • Get: This method has two overloads. One retrieves the value of an element at a given position. The other retrieves the values of all the elements available in the UI matching the selector.

  • FindPositionByText: This method finds the position of an element based on the text it contains.

  • WaitForMinimumOne: This method waits until at least one element appears.

  • WaitForElementVisible: This method waits until an element at a certain position is visible.

  • WaitForElementInvisible: This method waits until an element at a certain position is removed from the UI.