playwright-cucumber-ts-steps
Version:
A collection of reusable Playwright step definitions for Cucumber in TypeScript, designed to streamline end-to-end testing across web, API, and mobile applications.
646 lines (645 loc) • 23.7 kB
TypeScript
import type { DataTable } from "@cucumber/cucumber";
import { CustomWorld } from "../helpers/world";
/**
* Enables fake timers for the current page, fixing the time at the moment this step is executed.
* This is useful for testing time-dependent UI components without actual time passing.
*
* ```gherkin
* When I use fake timers
* ```
*
* @example
* When I use fake timers
* And I go to "/countdown-page"
* When I advance timers by 1000 milliseconds
* Then I should see text "9 seconds remaining"
*
* @remarks
* This step uses Playwright's `page.clock.setFixedTime()` to control the browser's internal
* clock. All subsequent time-related operations (like `setTimeout`, `setInterval`, `Date.now()`)
* will operate based on this fixed time. Use {@link When_I_advance_timers_by_milliseconds | "When I advance timers by X milliseconds"}
* or {@link When_I_advance_timers_by_seconds | "When I advance timers by X seconds"} to progress time.
* To revert, use {@link When_I_use_real_timers | "When I use real timers"}.
* @category Timer Steps
*/
export declare function When_I_use_fake_timers(this: CustomWorld): Promise<void>;
/**
* Restores real timers for the current page, releasing control over the browser's internal clock.
*
* ```gherkin
* When I use real timers
* ```
*
* @example
* When I use fake timers
* When I advance timers by 10 seconds
* When I use real timers
*
* @remarks
* This step uses Playwright's `page.clock.useRealTimers()`. After this step, `setTimeout`, `setInterval`,
* and other time-related functions will behave normally, using the system's real time.
* @category Timer Steps
*/
export declare function When_I_use_real_timers(this: CustomWorld): Promise<void>;
export declare function When_I_advance_timers_by_milliseconds(this: CustomWorld, ms: number): Promise<void>;
/**
* Advances fake timers by the given number of seconds. Requires fake timers to be enabled.
*
* ```gherkin
* When I advance timers by {int} seconds
* ```
*
* @param seconds - The number of seconds to advance the fake clock by.
*
* @example
* When I use fake timers
* When I advance timers by 2 seconds
*
* @remarks
* This step converts seconds to milliseconds and uses Playwright's `page.clock.tick()`.
* It will only have an effect if {@link When_I_use_fake_timers | "When I use fake timers"}
* has been called previously. If real timers are active, a warning will be logged.
* @category Timer Steps
*/
export declare function When_I_advance_timers_by_seconds(this: CustomWorld, seconds: number): Promise<void>;
/**
* Waits for the given number of seconds using `setTimeout`. This is a real-time wait.
*
* ```gherkin
* When I wait {int} second[s]
* ```
*
* @param seconds - The number of seconds to wait.
*
* @example
* When I wait 3 seconds
*
* @remarks
* This step pauses test execution for the specified duration using Node.js `setTimeout`.
* It's generally preferred to use explicit waits for element conditions (e.g., `toBeVisible`)
* over arbitrary waits, but this can be useful for debugging or waiting for external factors.
* @category General Action Steps
*/
export declare function When_I_wait_seconds(seconds: number): Promise<void>;
/**
* Waits for the given number of milliseconds using `setTimeout`. This is a real-time wait.
*
* ```gherkin
* When I wait {int} millisecond[s]
* ```
*
* @param ms - The number of milliseconds to wait.
*
* @example
* When I wait 500 milliseconds
*
* @remarks
* This step pauses test execution for the specified duration using Node.js `setTimeout`.
* It's generally preferred to use explicit waits for element conditions (e.g., `toBeVisible`)
* over arbitrary waits, but this can be useful for debugging or waiting for external factors.
* @category General Action Steps
*/
export declare function When_I_wait_milliseconds(this: CustomWorld, ms: number): Promise<void>;
/**
* Sets the default step timeout for all subsequent Cucumber steps.
* This can override the global timeout set in `cucumber.js` configuration.
*
* ```gherkin
* When I set step timeout to {int} ms
* ```
*
* @param timeoutMs - The new default timeout in milliseconds.
*
* @example
* When I set step timeout to 10000 ms
* And I find element by selector "#slow-loading-element"
*
* @remarks
* This step uses Cucumber's `setDefaultTimeout()` function. It applies to all following
* steps within the same test run. Use with caution as setting very high timeouts can
* hide performance issues.
* @category Configuration Steps
*/
export declare function When_I_set_step_timeout_to(this: CustomWorld, timeoutMs: number): void;
/**
* Triggers a generic DOM event of the given type on the element matching the provided selector.
*
* ```gherkin
* When I trigger {string} event on {string}
* ```
*
* @param eventType - The type of DOM event to trigger (e.g., "change", "input", "focus").
* @param selector - The CSS selector of the element to trigger the event on.
*
* @example
* When I trigger "change" event on ".my-input"
*
* @remarks
* This step uses Playwright's `locator.evaluate()` to dispatch a new `Event` directly
* on the DOM element. It can be useful for simulating browser-level events that
* might not be covered by Playwright's high-level actions (like `fill` for `input` events).
* @category Event Steps
*/
export declare function When_I_trigger_event_on_selector(this: CustomWorld, eventType: string, selector: string): Promise<void>;
/**
* Triggers a generic DOM event of the given type on the previously selected element.
*
* ```gherkin
* When I trigger event {string}
* ```
*
* @param eventName - The name of the event to dispatch (e.g., "change", "input", "blur").
*
* @example
* When I find element by selector ".my-input"
* And I trigger event "change"
*
* @remarks
* This step requires a preceding step that sets the {@link CustomWorld.element | current element}.
* It uses Playwright's `locator.dispatchEvent()` to dispatch the specified event.
* @category Event Steps
*/
export declare function When_I_trigger_event(this: CustomWorld, eventName: string): Promise<void>;
/**
* Removes focus from the previously selected element.
*
* ```gherkin
* When I blur
* ```
*
* @example
* When I find element by selector "input[name='username']"
* And I blur
*
* @remarks
* This step requires a preceding step that sets the {@link CustomWorld.element | current element}.
* It uses `locator.evaluate()` to call the DOM `blur()` method on the element,
* simulating a loss of focus.
* @category Event Steps
*/
export declare function When_I_blur(this: CustomWorld): Promise<void>;
/**
* Focuses the previously selected element.
*
* ```gherkin
* When I focus
* ```
*
* @example
* When I find element by selector "input[name='search']"
* And I focus
*
* @remarks
* This step requires a preceding step that sets the {@link CustomWorld.element | current element}.
* It uses Playwright's `locator.focus()` to bring the element into focus, simulating
* a user tabbing to or clicking on the element.
* @category Event Steps
*/
export declare function When_I_focus(this: CustomWorld): Promise<void>;
/**
* Logs a message to the test output (stdout/console).
*
* ```gherkin
* When I log {string}
* ```
*
* @param message - The string message to log.
*
* @example
* When I log "Test scenario started"
*
* @remarks
* This step is useful for injecting debugging or informative messages directly
* into the Cucumber test report or console output during test execution.
* @category Debugging Steps
*/
export declare function When_I_log(this: CustomWorld, message: string): Promise<void>;
/**
* Triggers a debugger statement, pausing test execution if a debugger is attached.
*
* ```gherkin
* When I debug
* ```
*
* @example
* When I find element by selector "#problematic-button"
* And I debug
* When I click current element
*
* @remarks
* This step is extremely useful for interactive debugging. When executed with a debugger
* (e.g., VS Code debugger attached to your Node.js process), it will pause execution
* at this point, allowing you to inspect the browser state, variables, etc.
* @category Debugging Steps
*/
export declare function When_I_debug(): Promise<void>;
/**
* Takes a full-page screenshot of the current page and saves it with the given name.
* The screenshot will be saved in the `e2e/screenshots/` directory (relative to your project root).
*
* ```gherkin
* When I screenshot {string}
* ```
*
* @param name - The desired filename for the screenshot (without extension).
*
* @example
* When I screenshot "dashboard-view"
*
* @remarks
* This step creates a PNG image. The `fullPage: true` option ensures that the
* entire scrollable height of the page is captured.
* @category Screenshot Steps
*/
export declare function When_I_screenshot_named(this: CustomWorld, name: string): Promise<void>;
/**
* Takes a full-page screenshot of the current page and saves it with a timestamped filename.
* The screenshot will be saved in the `screenshots/` directory (relative to your project root).
*
* ```gherkin
* When I screenshot
* ```
*
* @example
* When I screenshot
*
* @remarks
* This step is useful for quick visual debugging or capturing the state of the UI at
* various points in the test without needing to manually name each file.
* The filename will be in the format `screenshots/screenshot-TIMESTAMP.png`.
* @category Screenshot Steps
*/
export declare function When_I_screenshot(this: CustomWorld): Promise<void>;
/**
* Navigates the browser to the given URL or an aliased URL.
* If a relative path is provided (starts with `/`), it will be prepended with `process.env.BASE_URL`.
*
* ```gherkin
* When I visit {string}
* ```
*
* @param urlOrAlias - The URL to visit, or an alias (prefixed with `@`) pointing to a URL.
*
* @example
* When I visit "/dashboard"
* When I visit "https://www.example.com"
* Given I store "https://my.app.com/profile" as "profilePageUrl"
* When I visit "@profilePageUrl"
*
* @remarks
* This step uses Playwright's `page.goto()`. Ensure `BASE_URL` environment variable is set
* if you are using relative paths.
* @category Page Navigation Steps
*/
export declare function When_I_visit(this: CustomWorld, urlOrAlias: string): Promise<void>;
/**
* Reloads the current page.
*
* ```gherkin
* When I reload the page
* ```
*
* @example
* When I reload the page
*
* @remarks
* This step is equivalent to hitting the browser's reload button.
* It uses Playwright's `page.reload()`.
* @category Page Navigation Steps
*/
export declare function When_I_reload_the_page(this: CustomWorld): Promise<void>;
/**
* Navigates back in the browser's history.
*
* ```gherkin
* When I go back
* ```
*
* @example
* Given I visit "/page1"
* And I visit "/page2"
* When I go back
* Then I should be on "/page1"
*
* @remarks
* This step is equivalent to hitting the browser's back button.
* It uses Playwright's `page.goBack()`.
* @category Page Navigation Steps
*/
export declare function When_I_go_back(this: CustomWorld): Promise<void>;
/**
* Navigates forward in the browser's history.
*
* ```gherkin
* When I go forward
* ```
*
* @example
* Given I visit "/page1"
* And I visit "/page2"
* When I go back
* When I go forward
* Then I should be on "/page2"
*
* @remarks
* This step is equivalent to hitting the browser's forward button.
* It uses Playwright's `page.goForward()`.
* @category Page Navigation Steps
*/
export declare function When_I_go_forward(this: CustomWorld): Promise<void>;
/**
* Pauses the test execution in debug mode.
* This is useful for inspecting the browser state interactively during test runs.
*
* ```gherkin
* When I pause
* ```
*
* @example
* When I perform an action
* And I pause
* Then I assert something visually
*
* @remarks
* When running tests in debug mode (e.g., with `npx playwright test --debug`),
* this step will open Playwright's inspector, allowing you to step through
* actions, inspect elements, and troubleshoot. The test will resume when you
* continue from the inspector.
* @category Debugging Steps
*/
export declare function When_I_pause(this: CustomWorld): Promise<void>;
/**
* Stores a new date calculated by offsetting an existing aliased date by a given amount and unit.
*
* ```gherkin
* When I store {string} {int} {word} {word} as "{word}"
* ```
*
* @param baseAlias - The alias of an existing date string in `this.data` (e.g., "today").
* @param amount - The numerical amount to offset by (e.g., 2, 5).
* @param unit - The unit of time (e.g., "days", "months", "hours").
* @param direction - Whether to offset "before" or "after" the base date.
* @param newAlias - The alias under which to store the newly calculated date.
*
* @example
* Given I store "2024-01-15" as "invoiceDate"
* When I store "invoiceDate" 30 days after as "dueDate"
* Then the value of alias "dueDate" should be "2024-02-14"
*
* @remarks
* This step uses the `dayjs` library for date manipulation. The `baseAlias` must
* point to a valid date string that `dayjs` can parse. The `unit` must be one of:
* "second", "minute", "hour", "day", "week", "month", "year" (plural forms also supported).
* The new date is stored in `this.data` in "YYYY-MM-DD" format.
* @category Data Manipulation Steps
*/
export declare function When_I_store_date_offset(this: CustomWorld, baseAlias: string, amount: number, unit: string, direction: string, // "before" or "after"
newAlias: string): Promise<void>;
/**
* Switches the current Playwright context to an iframe located by a CSS selector.
* The step waits for the iframe's `body` element to be visible before proceeding.
*
* ```gherkin
* When I switch to iframe with selector {string}
* ```
*
* @param selector - The CSS selector for the iframe element (e.g., "#my-iframe", "iframe[name='chatFrame']").
*
* @example
* When I switch to iframe with selector "#payment-form-iframe"
* And I find element by placeholder text "Card Number"
* And I type "1234..."
*
* @remarks
* Once inside an iframe, all subsequent element finding and interaction steps will
* target elements within that iframe. To exit the iframe context, use
* {@link When_I_exit_iframe | "When I exit iframe"}.
* @category IFrame Steps
*/
export declare function When_I_switch_to_iframe_with_selector(this: CustomWorld, selector: string): Promise<void>;
/**
* Switches the current Playwright context to an iframe located by its title attribute.
*
* ```gherkin
* When I switch to iframe with title {string}
* ```
*
* @param title - The title of the iframe to switch to.
*
* @example
* When I switch to iframe with title "My Iframe"
* And I find element by label text "Card Holder"
*
* @remarks
* This step iterates through all frames on the page to find one whose title matches
* (case-insensitively, partially matched with `includes`). Once found, subsequent
* element operations will target elements within this iframe. To exit, use
* {@link When_I_exit_iframe | "When I exit iframe"}.
* @category IFrame Steps
*/
export declare function When_I_switch_to_iframe_with_title(this: CustomWorld, title: string): Promise<void>;
/**
* Switches the current Playwright context to an iframe located by a CSS selector,
* and then waits for specific text to become visible inside that iframe.
*
* ```gherkin
* When I switch to iframe with selector {string} and wait for text {string}
* ```
*
* @param selector - The CSS selector for the iframe element.
* @param expectedText - The text string to wait for inside the iframe.
*
* @example
* When I switch to iframe with selector "#dynamic-content-iframe" and wait for text "Content Loaded"
*
* @remarks
* This step combines switching into an iframe with a wait condition, which is
* useful for dynamic iframe content. The `expectedText` must be present
* and visible inside the iframe. To exit the iframe context, use
* {@link When_I_exit_iframe | "When I exit iframe"}.
* @category IFrame Steps
*/
export declare function When_I_switch_to_iframe_with_selector_and_wait_for_text(this: CustomWorld, selector: string, expectedText: string): Promise<void>;
/**
* Exits the current iframe context, returning the Playwright context to the main page.
* All subsequent element finding and interaction steps will operate on the main page.
*
* ```gherkin
* When I exit iframe
* ```
*
* @example
* When I switch to iframe with selector "#my-iframe"
* And I fill "my data"
* When I exit iframe
* And I click "Main Page Button"
*
* @remarks
* This step is crucial for navigating back to the main document after interacting
* with elements inside an iframe. It sets `this.frame` back to `undefined` (or the main page locator).
* @category IFrame Steps
*/
export declare function When_I_exit_iframe(this: CustomWorld): void;
/**
* Performs a specified action (e.g., click, hover, check, uncheck, focus, blur)
* on a subset of the previously stored elements (first N, last N, or random N).
*
* ```gherkin
* When I {word} the {word} {int}
* ```
*
* @param action - The action to perform (e.g., "click", "hover", "check", "uncheck", "focus", "blur", "fill").
* @param mode - The selection mode: "first", "last", or "random".
* @param count - The number of elements to apply the action to.
* @param table - (Optional) A Cucumber DataTable for action-specific options (e.g., `ClickOptions`).
*
* @example
* Given I find elements by selector ".item-checkbox"
* When I check the first 2
* When I hover the last 3
*
* @remarks
* This step requires that `this.elements` (a Playwright `Locator` that points to multiple
* elements) has been populated by a preceding step (e.g., `When I find elements by selector`).
* The `action` must be one of the supported actions. The `count` specifies how many of
* the matched elements to target.
* @category Multi-Element Action Steps
*/
export declare function When_I_perform_action_on_subset_of_elements(this: CustomWorld, action: string, mode: string, count: number, table?: DataTable): Promise<void>;
/**
* Performs a specified action (e.g., click, hover, check, uncheck, focus, blur)
* on the Nth element of the previously stored elements collection.
*
* ```gherkin
* When I {word} the {int}(?:st|nd|rd|th) element
* ```
*
* @param action - The action to perform (e.g., "click", "hover", "check", "uncheck", "focus", "blur", "fill").
* @param nth - The 1-based index of the element to target (e.g., 1 for 1st, 2 for 2nd).
* @param table - (Optional) A Cucumber DataTable for action-specific options.
*
* @example
* Given I find elements by selector ".product-card"
* When I click the 2nd element
* When I fill the 1st element
*
* @remarks
* This step requires that `this.elements` has been populated by a preceding step.
* It targets a single element at a specific 1-based ordinal position within that collection.
* The `action` must be one of the supported actions.
* @category Multi-Element Action Steps
*/
export declare function When_I_perform_action_on_nth_element(this: CustomWorld, action: string, nth: number, table?: DataTable): Promise<void>;
/**
* Presses a specific key on the previously selected element.
*
* ```gherkin
* When I press key {string}
* ```
*
* @param key - The key to press (e.g., "Enter", "Escape", "ArrowDown", "Tab").
*
* @example
* When I find element by selector "input[name='email']"
* And I type "my query"
* When I press key "Enter"
*
* @remarks
* This step requires a preceding step that sets the {@link CustomWorld.element | current element}.
* It first focuses the element and then simulates a key press.
* This is useful for triggering keyboard shortcuts or submitting forms via "Enter".
* @category Keyboard Interaction Steps
*/
export declare function When_I_press_key(this: CustomWorld, key: string): Promise<void>;
/**
* Sets the browser viewport to emulate a specific Playwright device profile and orientation.
* This will close the current browser context and open a new one with the specified device settings.
*
* ```gherkin
* When I set viewport to {string}
* When I set viewport to {string} and {string}
* ```
*
* @param deviceInput - The name of the Playwright device (e.g., "iPhone 12", "iPad", "Desktop Chrome").
* @param orientation - (Optional) The orientation, either "landscape" or "portrait" (default if not specified).
*
* @example
* When I set viewport to "iPhone 12"
* When I set viewport to "iPad" and "landscape"
*
* @remarks
* This step creates a *new* browser context and page, so any previous page state or
* setup (like routes, localStorage) will be reset.
* The `deviceInput` is normalized to match Playwright's `devices` object keys.
* @category Browser Context Steps
*/
export declare function When_I_set_viewport_to_device(this: CustomWorld, deviceInput: string, orientation?: string): Promise<void>;
/**
* Sets the viewport to the given width and height in pixels.
* This will close the current browser context and open a new one with the specified dimensions.
*
* ```gherkin
* When I set viewport to {int}px by {int}px
* ```
*
* @param width - The desired viewport width in pixels.
* @param height - The desired viewport height in pixels.
*
* @example
* When I set viewport to 1280px by 720px
*
* @remarks
* This step creates a *new* browser context and page, so any previous page state or
* setup (like routes, localStorage) will be reset.
* @category Browser Context Steps
*/
export declare function When_I_set_viewport_to_dimensions(this: CustomWorld, width: number, height: number): Promise<void>;
/**
* Sets a specific Playwright page configuration property to the given value.
* This can be used to dynamically change page-level settings during a test.
*
* ```gherkin
* When I set Playwright config {word} to {string}
* ```
*
* @param key - The name of the Playwright `Page` property to set (e.g., "userAgent", "defaultTimeout").
* @param value - The string value to set the property to. Note: All values are treated as strings.
*
* @example
* When I set Playwright config "userAgent" to "MyCustomAgent"
*
* @remarks
* This step directly assigns a value to a property on the `this.page` object.
* It's important to know which properties are settable and what their expected
* types are. Using incorrect keys or values may lead to unexpected behavior or errors.
* Not all Playwright page properties are designed to be set this way after page creation.
* @category Configuration Steps
*/
export declare function When_I_set_playwright_page_config_key(this: CustomWorld, key: string, value: string): Promise<void>;
/**
* Sets multiple Playwright page configuration properties using a data table.
*
* ```gherkin
* When I set Playwright config
* | key | value |
* | userAgent | MyAgent |
* | defaultTimeout | 5000 |
* ```
*
* @param table - A Cucumber DataTable with two columns: `key` (the property name)
* and `value` (the string value to set).
*
* @example
* When I set Playwright config
* | key | value |
* | userAgent | TestBot |
* | defaultTimeout | 10000 |
*
* @remarks
* Similar to the single-key version, this step dynamically assigns values to
* properties on the `this.page` object. All values from the data table are
* treated as strings. Use with caution, understanding which properties can
* be dynamically set.
* @category Configuration Steps
*/
export declare function When_I_set_playwright_page_config_from_table(this: CustomWorld, table: DataTable): Promise<void>;