Skip to content

jagobond/PageObjectGenerator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

.NET Selenium Page Object Generator

A .NET 8.0 console application that takes a URL as input and automatically generates a basic C# Page Object class suitable for use in Selenium-based test automation projects, particularly those using frameworks like Reqnroll (SpecFlow).

The generated class includes:

  • CSS or XPath locators for common interactive HTML elements (inputs, buttons, links, selects, textareas).
  • Basic interaction methods (Click, EnterText, GetText, Select) for these elements.
  • Integration of WebDriverWait and ExpectedConditions to handle dynamic waits before interactions.

Goal: To accelerate the creation of Page Objects by automating the initial boilerplate code and locator identification.

Features

  • Fetches HTML content from a given URL.
  • Parses the HTML using HtmlAgilityPack.
  • Identifies potentially relevant interactive elements (<input>, <button>, <a>, <select>, <textarea>).
  • Generates locators using a priority system:
    1. Id (if unique and not likely dynamic)
    2. Name
    3. data-testid attribute (as CSS Selector)
    4. CSS Selector (based on tag, type, class, other attributes)
    5. XPath (as a fallback, typically based on attributes or text)
  • Sanitizes element information to create valid C# PascalCase names for methods and fields, handling duplicates and keywords.
  • Generates a C# class file (.cs) containing:
    • using statements for Selenium and common types.
    • A constructor accepting IWebDriver.
    • Initialization of WebDriverWait.
    • private static readonly By fields for each identified element locator.
    • Public methods for interacting with elements (e.g., ClickLoginButton(), EnterUsernameText(string username)).
    • Built-in explicit waits (_wait.Until(...)) before most actions (e.g., ElementToBeClickable, ElementIsVisible).
    • Basic error handling (try-catch) within interaction methods.

Prerequisites

Setup

  1. Clone or Download: Get the source code for this project.

    git clone <repository-url>
    cd PageObjectGenerator

    (Replace <repository-url> with the actual URL of your Git repository)

  2. Build the Project:

    dotnet build

    This will restore NuGet packages (like HtmlAgilityPack) and compile the application.

Usage

Run the generator from your terminal within the project directory (PageObjectGenerator).

Syntax:

dotnet run -- <URL> <OutputFilePath> [ClassName]

Arguments:

  • <URL>: (Required) The full URL of the web page you want to generate a Page Object for (e.g., https://github.com/login). Must start with http:// or https://.
  • <OutputFilePath>: (Required) The full or relative path where the generated C# file (.cs) should be saved (e.g., ./output/LoginPage.cs or ../MyReqnrollProject/PageObjects/LoginPage.cs).
    • If the directory doesn't exist, it will be created.
    • If the path doesn't end with .cs, the extension will be appended automatically.
  • [ClassName]: (Optional) The desired name for the generated C# class.
    • If omitted, the class name will be derived from the <OutputFilePath> (e.g., LoginPage.cs results in class LoginPage).
    • The name will be sanitized to be a valid C# identifier.

Important: Note the -- separator between dotnet run and the application arguments. This is required to pass arguments correctly to the application itself.

Examples:

# Generate a page object for Google search, save it locally
dotnet run -- "https://www.google.com" "./GoogleSearchPage.cs" GoogleSearchPage

# Generate a page object for GitHub login, save it to a specific project structure
# (Assumes the test project is in a sibling directory)
dotnet run -- "https://github.com/login" "../MyTests/PageObjects/GitHubLoginPage.cs"

# Generate a page object, letting the class name be derived from the file name
dotnet run -- "https://example.com" "./ExampleComPage.cs"

Generated Code Overview

The output .cs file will contain a class structure like this:

// Generated by PageObjectGenerator
// Timestamp: ...

using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;
using SeleniumExtras.WaitHelpers;
// ... other usings

namespace YourProject.PageObjects // <-- CHANGE THIS NAMESPACE!
{
    public class GeneratedClassName // e.g., LoginPage
    {
        private readonly IWebDriver _driver;
        private readonly WebDriverWait _wait;
        private readonly TimeSpan _defaultWaitTimeout = TimeSpan.FromSeconds(10);

        public GeneratedClassName(IWebDriver driver)
        {
            _driver = driver ?? throw new ArgumentNullException(nameof(driver));
            _wait = new WebDriverWait(_driver, _defaultWaitTimeout);
            // Optional: Add wait for page load indicator here
        }

        // --- Locators ---
        private static readonly By _elementNameLocator = By.Id("someId");
        private static readonly By _anotherElementLocator = By.CssSelector("input[type='submit']");
        // ... more locators

        // --- Interaction Methods ---
        public void ClickElementName()
        {
            // ... wait and click logic ...
        }

        public void EnterAnotherElementText(string text)
        {
            // ... wait, clear, and sendkeys logic ...
        }

        public string GetSomeElementText()
        {
            // ... wait and get text/value logic ...
        }

        public bool IsElementDisplayed()
        {
             // ... wait and check displayed logic ...
        }

        // ... more methods (Select for dropdowns, etc.)

        // --- Helper Methods --- (Placeholder for custom waits)
    }
}

Key points about the generated code:

  • Namespace: Defaults to YourProject.PageObjects. You MUST change this to match the namespace structure of your target Reqnroll/Selenium project.
  • Dependencies: The class assumes your test project has references to Selenium.WebDriver, Selenium.Support, and DotNetSeleniumExtras.WaitHelpers NuGet packages.
  • Constructor: Requires an IWebDriver instance.
  • Waits: Uses WebDriverWait and ExpectedConditions before actions.

Important Considerations & Limitations

  • LOCATOR REVIEW IS ESSENTIAL: Auto-generated locators are a starting point. They might be brittle, non-unique, or based on attributes that change. Always review and refine the generated locators. Prefer stable attributes like id, name, or custom data-testid attributes whenever possible.
  • Dynamic Content: The generator fetches the initial HTML source. It does not execute JavaScript. Elements loaded dynamically after the initial page load (via AJAX, etc.) might be missed or have inaccurate locators generated based on their initial state (if any).
  • Frames/Iframes: The current version does not explicitly handle elements within <iframe> or <frame> tags. You will need to manually add logic to switch frames (driver.SwitchTo().Frame(...)) in your test code or enhance the generator.
  • Shadow DOM: Elements within a Shadow DOM cannot be located using standard Selenium locators. This tool does not generate code to handle Shadow DOM interactions (which typically require ExecuteScript).
  • Complex Interactions: Only basic interactions (click, type, select, get text) are generated. Actions like drag-and-drop, hover menus, file uploads, handling alerts, etc., need to be added manually.
  • Wait Strategy: While explicit waits are included, the default timeout or conditions might need adjustment based on your specific application's performance and behaviour. Consider adding more sophisticated custom wait methods (e.g., WaitForAjaxToComplete, WaitForSpinnerToDisappear).

Reqnroll/Selenium Integration

  1. Place the File: Move the generated .cs file into the appropriate Page Objects directory within your test project.

  2. Adjust Namespace: Open the file and change the namespace YourProject.PageObjects line to match your project's structure.

  3. Install Dependencies: Ensure your test project has the necessary NuGet packages:

    • Selenium.WebDriver
    • Selenium.Support
    • DotNetSeleniumExtras.WaitHelpers
  4. Instantiate in Steps: In your Reqnroll step definition files, you can instantiate the generated page object, passing the IWebDriver instance (which is typically managed by your test setup, possibly via ScenarioContext or a Dependency Injection container).

    // Example in a Reqnroll Step Definition class
    using YourProject.PageObjects; // Use the correct namespace
    // ... other usings
    
    [Binding]
    public class LoginSteps
    {
        private readonly IWebDriver _driver;
        private readonly LoginPage _loginPage; // Assuming generated class is LoginPage
    
        // Constructor injection is common
        public LoginSteps(IWebDriver driver)
        {
            _driver = driver;
            _loginPage = new LoginPage(_driver);
        }
    
        [When(@"I enter username ""(.*)""")]
        public void WhenIEnterUsername(string username)
        {
            _loginPage.EnterUsernameText(username); // Use generated method
        }
    
        [When(@"I click the login button")]
        public void WhenIClickTheLoginButton()
        {
            _loginPage.ClickLoginButton(); // Use generated method
        }
        // ... other steps
    }

Dependencies

  • HtmlAgilityPack: Used for parsing the HTML content.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages