class-act
TypeScript icon, indicating that this package has built-in type declarations

0.0.12 • Public • Published

ClassAct for Playwright

Overview

ClassAct is a lightweight library that wraps Playwright to enhance automated testing and offer extended capabilities. ClassAct allows you to leverage the power of Playwright with less code.

Basic Features

  • Extended Page and Element Capabilities: Adds additional functionality to the Playwright page and element locators.
  • Page Object Model (POM): Provides a clean and DRY Page Object Model (POM) framework.
  • Mocking: Adds ability to easily mock API interactions, current user, and current date/time, allowing tests to be deterministic and fast.

Installation

npm install class-act --save-dev

Configuration

Call setClassActConfig() to configure ClassAct. Since this method call must occur prior to any test execution, a good place to call this is in playwright.config.ts.

import { setClassActConfig } from 'class-act';
...
setClassActConfig({
    siteUrl: "http://localhost:3000",
    apiUrl: "http://localhost:5000",
    testIdAttribute: "test-id",
    mockFileDirectory: "e2e/mocks/files",
    storagePath: "state.json",
    launchSettings: {
        headless: false,
        devtools: false,
        slowMo: 2000,
    },
});

Creating Page Objects

ClassAct allows you to create page objects with ease.

For creating your page objects, there are two objects you will need. These classes serve as wrappers to Playwright page and element locators.

  • Page represents any routeable view in your application. This should be the base class for any pages you create.
  • PageElement represents any HTML element. You can cast elements on your page directly to class, or extent your element by creating your own element class that inherits from PageElement.

When defining the elements within the structure of your page, use one of the following methods:

  • find(selector, type)
  • findAll(selector, type)

Your selector (string) can be any standard CSS selector. You can also use the @ symbol to locate your element using the test-id attribute, as configured when you call setClassActConfig().

The type passed to find or findAll must be an class that inherits from PageElement.

  1. Define the page object under test. Be sure to inherit from Page, or a base class inheriting from page.

    import { Page, PageElement, PageFormElement } from 'class-act';
    ...
    export class SearchPage extends Page {
        path = "search";
    
        get form() {
            return this.find("form", SearchForm);
        }
    
        get results() {
            return this.findAll("#results>div", SearchResult);
        }
    }
  2. Define complex elements located on the page.

    export class SearchForm extends PageElement {
        get keywordField() {
            return this.find("input", PageFormElement);
        }
        get searchButton() {
            return this.find("button", PageElement);
        }
    }
    ...

Creating Specs

  1. Initialize the App:
    import { App } from 'class-act';
    ...
    const app = await App.init();
    Optionally, you can provide mocks for the API interactions, browser storage, and/or dateTime during initialization.
    const app = await App.init({
        sessionStorage: [
            { 'accessToken': '12195f53-6ce3-4b5c-907d-6fe8408d53d5' }
        ],
        api: apiDefinitions,
        dateTime: new Date(2024, 1, 1)
    });
  2. Navigate to a page:
    const searchPage = await app.navigate(SearchPage);
  3. Interact with elements using page objects.
    await searchPage.form.keywordField.setValue('Test');
    await searchPage.form.searchButton.click();
    
    expect(await searchPage.loadingIndicator.isVisible);

Creating Endpoints

Creating definitions for API endpoints serves two primary purposes:

  1. Data mocking
  2. Pausing test exection until an one or more API calls have completed

Setup definition for each API endpoint:

    import { ApiMethod, ApiRequest } from "../class-act";

    export class GetPeopleSearch extends ApiRequest {
        method: ApiMethod = "GET";
        path = "search";

        constructor(keyword: string) {
            super({ queryParams: { keyword } });
        }
    }

Be sure to properly map parameters to routeParams, queryParams, or body.

Creating API Mocks

Variable parameters:
export const testData = [
  mock(
    new api.GetUserById("user@test.com"),
    new SuccessResponse({ name: "Test User", dashboards: [], theme: "light" }),
  ),
  mock(
    new api.GetUserById("john@test.com"),
    new SuccessResponse({ name: "John Tester", dashboards: [], theme: "dark" }),
  ),
  ...
];
Sourcing responses from a file:
  mock(
    new api.GetSearchResults("test"),
    new SuccessResponse(fromFile("searchResults.json")),
  )
Failure responses:
  mock(
    new api.GetSearchResults("fail"),
    new FailureResponse(404)
  )

Type Definitions

ClassActConfig (interface)

The ClassActConfig interface defines the configuration settings used across various components of the application, particularly those interacting with the web and testing environments.

Properties
  • siteUrl: string - The base URL of the site under test.
  • apiUrl: string - The base URL for API calls.
  • testIdAttribute: string - The attribute name used to identify elements during testing (e.g., data-testid).
  • mockFileDirectory: string - Directory path where mock files for testing are stored.
  • storageStateDirectory: string - Directory path where state files are stored.
  • launchSettings: LaunchOptions - Configuration options for launching the browser or other test environments.

App

The App class serves as a Page Object wrapper for Playwright's Browser and Context objects, providing a structured way to interact with a web application's browser environment. It includes methods for navigation, mocking data, and handling API calls. Instances of this class should be created using the static init method.

Constructors
  • The constructor is private to enforce the use of the init method for creating instances.
Properties
  • config (protected): ClassActConfig - Configuration settings for the class instance.
  • browser (protected): playwright.Browser | undefined - Holds the Playwright Browser instance, if initialized.
  • context (protected): playwright.BrowserContext | undefined - Holds the Playwright BrowserContext instance, if initialized.
Methods
  • mockApi(apiMocks: ApiMock[]): void - Mocks API endpoints.

  • mockDateTime(dateTime: Date): void - Mocks the current date/time.

  • setLocale(locale: string): void - Sets the browser's default locale.

  • setCookies(cookies: Cookie[]): void - Adds cookies to the browser context.

  • setLocalStorage(items: StorageItem[]): void - Sets localStorage values on the browser.

  • setSessionStorage(items: StorageItem[]): void - Sets sessionStorage values on the browser.

  • currentPage<T extends Page>(type: new (page: playwright.Page) => T): Promise - Returns the page currently loaded in the context.

  • goBack<T extends Page>(type: new (page: playwright.Page) => T): Promise - Navigates backward in the browser history.

  • goForward<T extends Page>(type: new (page: playwright.Page) => T): Promise - Navigates forward in the browser history.

  • navigate<T extends Page>(type: new (page: playwright.Page) => T, params?: { route?: any; query?: any; hash?: string; }): Promise - Navigates to the provided page type, with optional route and query parameters.

Static Methods
  • init(options?: AppOptions): Promise - Initializes the application with optional configurations.
Example Usage
const app = await App.init({
  apiMocks: [
    new ApiMock("/api/data", { data: [1, 2, 3] })
  ],
  dateTime: new Date("2023-01-01")
});

const currentPage = await app.currentPage(HomePage);
await app.mockUser({ name: "Jane Doe" });
await app.navigate(SettingsPage);

AppOptions (interface)

AppOptions allows the app to be configured when calling App.init().

Properties
  • apiMocks: ApiMock[] - Sets substitutions for API interactions.
  • dateTime: dateTime - Sets the value of Date.now().
  • locale: string - Sets the browsers language property.
  • cookies: Cookie[] - Sets cookies.
  • localStorage: StorageItem[] - Sets localStorage.
  • sessionStorage: StorageItem[] - Sets sessionStorage.

Cookie (interface)

Properties
  • name: string - Unique identifier within domain and path.
  • value: string - Data stored in the cookie.
  • domain: string - Domain the cookie is valid for (defaults to creation domain).
  • path: string - Path on server the cookie is valid for (defaults to current page's path).
  • expires: number - Expiration time in seconds since Unix epoch (defaults to session cookie).
  • httpOnly: boolean - Only accessible by server, not client-side scripts (defaults to false).
  • secure: boolean - Only transmitted over secure connections (defaults to false).
  • sameSite: "Strict" | "Lax" | "None" - Controls cookie behavior in cross-site requests:

StorageItem (interface)

Properties
  • key: string - Key to use for storage item.
  • value: string - Serialized value of storage item.

Page

The Page class serves as an abstract base class for specific page objects within a web application managed by Playwright. It provides common functionalities like navigation, fetching page details, and handling page elements. Instances are generally created through navigation methods in the App class.

Constructor
  • The constructor takes a Playwright Page object and initializes the page properties. The constructor should not be used directly. Use the navigate() and method of App instead.
Properties
  • page (protected): playwright.Page - Reference to the Playwright Page object.
  • path (abstract): string - The specific path or route associated with the page.
  • config (protected): ClassActConfig - Global ClassAct configuration.
Methods
  • title: Promise<string> - Returns the title of the current page.
  • url: URL - Returns the URL of the current page.
  • params: { [k: string]: string } - Retrieves URL parameters as an object.
  • viewportSize: { width: number; height: number } | null - Returns the current viewport size of the page.
  • body: PageElement - Returns the main PageElement object representing the body of the page.
  • close(): Promise<void> - Closes the current page.
  • screenshot(options?: playwright.PageScreenshotOptions): Promise<Buffer> - Takes a screenshot of the current page.
  • setViewportSize(width: number, height: number): Promise<void> - Sets the viewport size of the page.
  • load(params?: { route?: any; query?: any; hash?: string; }): Promise<void> - Loads or reloads the page with optional parameters.
  • waitForUrl(url: string | RegExp | ((url: URL) => boolean), options?: { timeout?: number | undefined; waitUntil?: "load" | "domcontentloaded" | "networkidle" | "commit" | undefined; } | undefined): Promise<void> Waits for the main frame to navigate to the given URL.
  • waitForApiResponse(apiRequest: ApiRequest, timeout?: number): Promise<void> - Waits for a response to a specified API request.
  • waitForAllApiResponses(apiRequests: ApiRequest[], timeout?: number): Promise<void[]> - Waits for all responses to specified API requests.
  • executeScript<T>(script: Function, ...var_args: any[]): Promise<T> - Executes a script on the page and returns a result.
  • find<T extends PageElement>(selector: string, type: new (locator: playwright.Locator) => T): T - Finds the first element matching the selector and casts it to the specified type.
  • findAll<T extends PageElement>(selector: string, type: new (locator: playwright.Locator) => T): `PageElementCollection
Example Usage
class HomePage extends Page {
  get path() {
    return "/home";
  }

  async navigateToSettings() {
    return this.navigate(SettingsPage);
  }
}

const homePage = await app.currentPage(HomePage);
const title = await homePage.title;
const settingsPage = await homePage.navigateToSettings();

PageElement

The PageElement class wraps Playwright's Locator object, providing an API for interacting with specific elements on a web page. It encapsulates common DOM operations and ensures elements are accessed in a consistent manner across different page objects.

Constructor
  • Accepts a Playwright Locator object and initializes the element properties. The constructor should not be used directly. Use the find() method of Page and PageElement instead.
Properties
  • locator (protected): playwright.Locator - The Playwright Locator object associated with the element.
  • config (protected): ClassActConfig - Global ClassAct configuration.
Methods
  • selector: string - Returns the selector used to locate the element.
  • html: Promise<string> - Fetches the inner HTML of the element.
  • tagName: Promise<string> - Returns the tag name of the element.
  • id: Promise<string | null> - Retrieves the ID attribute of the element.
  • title: Promise<string | null> - Fetches the title attribute of the element.
  • testId: Promise<string | null> - Gets a custom attribute typically used for identifying elements in tests.
  • classList: Promise<DOMTokenList> - Returns the list of classes applied to the element.
  • height: Promise<number> - Returns the height of the element.
  • width: Promise<number> - Returns the width of the element.
  • text: Promise<string> - Fetches the visible text contained within the element.
  • isVisible: Promise<boolean> - Checks if the element is visible on the page.
  • isHidden: Promise<boolean> - Checks if the element is hidden on the page.
  • isEnabled: Promise<boolean> - Determines if the element is enabled.
  • isDisabled: Promise<boolean> - Checks if the element is disabled.
  • isInView: Promise<boolean> - Checks if the element is within the visible viewport.
  • click(): Promise<void> - Simulates a mouse click on the element.
  • dblclick(): Promise<void> - Simulates a double-click on the element.
  • dragTo(element: PageElement): Promise<void> - Drags the current element to another element.
  • scrollTo(): Promise<void> - Scrolls the page to the element.
  • scrollIntoView(): Promise<void> - Scrolls the element into the visible area of the browser window.
  • blur(): Promise<void> - Removes focus from the element.
  • focus(): Promise<void> - Sets focus on the element.
  • getAttribute(name: string): Promise<string | null> - Retrieves a specified attribute from the element.
  • getComputedStyle(property: string): Promise<string> - Gets the computed style of the element.
  • waitForLoad(timeout?: number): Promise<void> - Waits until the element is attached to the DOM.
  • waitForUnload(timeout?: number): Promise<void> - Waits until the element is detached from the DOM.
  • waitForVisible(timeout?: number): Promise<void> - Waits for the element to become visible.
  • waitForHidden(timeout?: number): Promise<void> - Waits for the element to become hidden.
  • find<T extends PageElement>(selector: string, type: new (locator: playwright.Locator) => T): T - Finds the first sub-element that matches the selector.
  • findAll<T extends PageElement>(selector: string, type: new (locator: playwright.Locator) => T): PageElementCollection<T> - Finds all sub-elements matching the selector.
Example Usage
const loginButton = this.find('#login-button', PageElement);
await loginButton.click();

PageElementCollection

The PageElementCollection class is designed to manage collections of PageElement objects, providing utilities to interact with multiple elements simultaneously. It facilitates operations on groups of elements found through specific selectors using Playwright's Locator.

Constructor
  • The constructor takes a Playwright Locator object and a constructor function for the PageElement type, initializing the collection properties. The constructor should not be used directly. Use the findAll() method of Page and PageElement instead.
Properties
  • locator (protected): playwright.Locator - The Playwright Locator used to define the collection of elements.
  • type (protected): new (locator: playwright.Locator) => T - The constructor function of the PageElement type for elements in the collection.
Methods
  • selector: string - Returns the selector used for locating the elements in the collection.
  • items: Promise<T[]> - Retrieves all elements in the collection as an array of PageElement objects.
  • count: Promise<number> - Returns the number of elements in the collection.
  • first: T - Returns the first element in the collection.
  • last: T - Returns the last element in the collection.
  • nth(index: number): T - Retrieves the nth element from the collection.
  • findByText(text: string | RegExp, exact?: boolean): T - Finds an element by its text content, with an option for exact match.
  • findByTitle(text: string | RegExp, exact?: boolean): T - Finds an element by its title attribute, with an option for exact match.
  • find(predicate: (value: T, index: number, obj: T[]) => boolean | Promise): Promise<T | undefined> - Finds an element based on a custom predicate function.
  • filter(predicate: (value: T, index: number, array: T[]) => boolean | Promise): Promise<T[]> - Filters elements in the collection based on a custom predicate function.
  • every(predicate: (value: T, index: number, array: T[]) => boolean | Promise): Promise<boolean> - Checks if every element in the collection satisfies the predicate.
  • some(predicate: (value: T, index: number, array: T[]) => boolean | Promise): Promise<boolean> - Checks if some elements in the collection satisfy the predicate.
  • map(callbackfn: (value: T, index: number, array: T[]) => V | Promise): Promise<V[]> - Creates a new array with the results of calling a provided function on every element in the calling array.
  • forEach(callbackfn: (value: T, index: number, array: T[]) => void | Promise): Promise<void> - Executes a provided function once for each element in the collection.
  • waitForLoad(timeout?: number): Promise<void> - Waits for all elements in the collection to be loaded in the DOM.
  • waitForUnload(timeout?: number): Promise<void> - Waits for all elements in the collection to be unloaded from the DOM.
Example Usage
const buttons = new PageElementCollection(page.locator('button'), ButtonElement);
await buttons.forEach(async (button) => await button.click());
const areAllButtonsVisible = await buttons.every(button => button.isVisible);

PageFormElement

PageFormElement extends PageElement to provide specific functionalities for interacting with form elements on a web page, such as input, textarea and select fields.

Properties
  • type: Promise<string | null> - Retrieves the type of the form element (e.g., text, checkbox).
  • value: Promise<string> - Gets the current value of the form element.
  • isChecked: Promise<boolean> - Determines whether a checkbox or radio button is checked.
  • isValid: undefined - Currently, this property is not implemented and returns undefined.
Methods
  • clear(): Promise<void> - Clears the value of the form element.
  • check(): Promise<void> - Checks a checkbox or radio button.
  • uncheck(): Promise<void> - Unchecks a checkbox or radio button.
  • setValue(value: string): Promise<void> - Sets the value of the form element.
  • appendValue(value: string): Promise<void> - Appends additional text to the current value of the form element.

PageHyperLink

PageHyperLink extends PageElement specifically for hyperlink elements, providing access to hyperlink-specific attributes.

Properties
  • href: Promise<string | null> - Retrieves the URL to which the hyperlink points.
  • target: Promise<string | null> - Gets the target frame or window in which the linked document will open.

PageImageElement

PageImageElement extends PageElement to cater specifically to image elements, allowing access to image-specific attributes.

Properties
  • src: Promise<string | null> - Retrieves the source URL of the image.
  • altText: Promise<string | null> - Gets the alternative text of the image, used for accessibility and when the image cannot be displayed.

ApiRequest (abstract)

ApiRequest is an abstract base class for defining API request details, including the method, path, and input parameters.

Constructor
  • Accepts optional ApiRequestInput to initialize request inputs.
Properties
  • inputs: ApiRequestInput - Contains input parameters like route parameters, query parameters, and data.
  • method (abstract): ApiMethod - Specifies the HTTP method of the request (GET, POST, PUT, DELETE).
  • path (abstract): string - Specifies the endpoint path.
  • config (protected): ClassActConfig - Global ClassAct configuration.
Methods
  • url: string - Constructs and returns the full URL for the request based on the path and inputs.

ApiRequestInput (interface)

The ApiRequestInput interface provides structure for input data used in API requests, including route parameters, query parameters, and body data.

Properties
  • routeParams: any - Parameters embedded in the route path.
  • queryParams: any - Parameters appended to the URL as query strings.
  • data: any - Data sent in the body of the request, applicable for methods like POST and PUT.

ApiMethod (type)

ApiMethod is a type defining the allowed HTTP methods for API requests. Accepted values are:

  • "GET"
  • "POST"
  • "PUT"
  • "DELETE"

ApiResponse (abstract)

ApiResponse is an abstract base class for defining the structure of API responses.

Properties
  • status (abstract): number | undefined - The HTTP status code of the response.
  • message (abstract): string | undefined - A message accompanying the status code.
  • data (abstract): any - The payload returned in the response.

SuccessResponse

SuccessResponse represents a successful API response structure, extending ApiResponse.

Constructor
  • Accepts optional any data to initialize the response data.
Properties
  • data: any - Data returned in the response.
  • status: number | undefined - The HTTP status code, typically in the 200 range.
  • message: string | undefined - Optional message describing the success.

FailureResponse

FailureResponse represents an error or failure in API response, extending ApiResponse.

Constructor
  • Requires status: number and accepts an optional message.
Properties
  • status: number - The HTTP status code, typically in the 400 or 500 range.
  • message: string | undefined - Optional message detailing the error.
  • data: any - Additional data related to the error.

ApiMock (interface)

The ApiMock interface is used to simulate API requests and responses, ideal for testing scenarios.

Properties
  • request: ApiRequest - Defines the API request details.
  • response: ApiResponse - Defines the expected response for the mock.

Readme

Keywords

Package Sidebar

Install

npm i class-act

Weekly Downloads

24

Version

0.0.12

License

MIT

Unpacked Size

50.3 kB

Total Files

4

Last publish

Collaborators

  • johnlawrimore