UNPKG

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.

433 lines (407 loc) 16.4 kB
import { Then } from "@cucumber/cucumber"; import { expect } from "@playwright/test"; import type { CustomWorld } from "../helpers/world"; // Assuming this path is correct // =================================================================================== // ASSERTIONS: ELEMENT EXISTENCE (IN DOM) // =================================================================================== /** * Asserts that at least one element matching the given selector exists in the DOM. * It does not necessarily check for visibility. * * ```gherkin * Then I see element {string} exists * ``` * * @param selector - The CSS selector of the element expected to exist. * * @example * Then I see element ".user-profile-card" exists * * @remarks * This step uses Playwright's `expect(locator).toHaveCount(1)` as a robust way to * assert that exactly one matching element is present in the DOM. If multiple elements * match, it will still pass as long as at least one exists (though `toHaveCount(1)` * would strictly mean *only one*). For asserting multiple elements, use "Then I count X elements". * @category Assertion Steps */ export async function Then_I_see_element_exists(this: CustomWorld, selector: string) { const locator = this.page.locator(selector); // Using toHaveCount(1) for "exists" implies expecting at least one, or exactly one. // If the intent is *at least one*, expect(locator).first().waitFor({state: 'attached'}) is also an option. // For strict "exists", toHaveCount(1) is good if you expect uniqueness. await expect(locator).toHaveCount(1, { timeout: 5000 }); this.log?.(`✅ Verified element "${selector}" exists in the DOM.`); } Then(/^I see element "([^"]+)" exists$/, Then_I_see_element_exists); /** * Asserts that the previously stored element exists in the DOM. * This checks for its presence, not necessarily its visibility. * * ```gherkin * Then I see element exists * ``` * * @example * When I find element by selector ".my-dialog" * Then I see element exists * * @remarks * This step requires a preceding step that sets the {@link CustomWorld.element | current element}. * It asserts that the stored element is attached to the DOM. * @category Assertion Steps */ export async function Then_I_see_stored_element_exists(this: CustomWorld) { if (!this.element) throw new Error("No element stored in context. Use a 'find' step before asserting."); // Playwright's toBeAttached is the most robust way to check for DOM existence await expect(this.element).toBeAttached({ timeout: 5000 }); this.log?.(`✅ Verified stored element exists in the DOM.`); } Then("I see element exists", Then_I_see_stored_element_exists); /** * Asserts that the previously stored element does NOT exist in the DOM. * * ```gherkin * Then I see element does not exist * ``` * * @example * When I find element by selector "#deleted-item" * Then I see element does not exist * * @remarks * This step requires a preceding step that sets the {@link CustomWorld.element | current element}. * It asserts that the stored element is detached from the DOM. * @category Assertion Steps */ export async function Then_I_see_stored_element_does_not_exist(this: CustomWorld) { if (!this.element) throw new Error("No element stored in context. Use a 'find' step before asserting."); // Playwright's not.toBeAttached is the most robust way to check for DOM non-existence await expect(this.element).not.toBeAttached({ timeout: 5000 }); this.log?.(`✅ Verified stored element does NOT exist in the DOM.`); } Then("I see element does not exist", Then_I_see_stored_element_does_not_exist); // =================================================================================== // ASSERTIONS: ELEMENT VISIBILITY (Stored Element) // =================================================================================== /** * Asserts that the previously stored element is visible in the viewport. * * ```gherkin * Then I see element is visible * ``` * * @example * When I find element by selector ".success-message" * Then I see element is visible * * @remarks * This step requires a preceding step that sets the {@link CustomWorld.element | current element}. * It uses Playwright's `expect(locator).toBeVisible()` which automatically waits * for the element to become visible. * @category Assertion Steps */ export async function Then_I_see_stored_element_is_visible(this: CustomWorld) { if (!this.element) throw new Error("No element stored in context to check visibility."); await expect(this.element).toBeVisible({ timeout: 5000 }); this.log?.(`✅ Verified stored element is visible.`); } Then("I see element is visible", Then_I_see_stored_element_is_visible); /** * Asserts that the previously stored element is NOT visible in the viewport. * * ```gherkin * Then I see element is not visible * ``` * * @example * When I find element by selector ".loading-spinner" * Then I see element is not visible * * @remarks * This step requires a preceding step that sets the {@link CustomWorld.element | current element}. * It uses Playwright's `expect(locator).not.toBeVisible()` which automatically waits * for the element to become hidden. * @category Assertion Steps */ export async function Then_I_see_stored_element_is_not_visible(this: CustomWorld) { if (!this.element) throw new Error("No element stored in context to check non-visibility."); await expect(this.element).not.toBeVisible({ timeout: 5000 }); this.log?.(`✅ Verified stored element is NOT visible.`); } Then("I see element is not visible", Then_I_see_stored_element_is_not_visible); // =================================================================================== // ASSERTIONS: ELEMENT EXISTENCE (Absence by Selector) // =================================================================================== /** * Asserts that no element matching the given selector exists in the DOM. * * ```gherkin * Then I see element {string} does not exist * ``` * * @param selector - The CSS selector of the element expected NOT to exist. * * @example * Then I see element ".old-feature-flag" does not exist * * @remarks * This step uses Playwright's `expect(locator).toHaveCount(0)` as a robust way to * assert that no matching elements are present in the DOM. * @category Assertion Steps */ export async function Then_I_see_element_does_not_exist(this: CustomWorld, selector: string) { const locator = this.page.locator(selector); await expect(locator).toHaveCount(0, { timeout: 5000 }); this.log?.(`✅ Verified element "${selector}" does NOT exist in the DOM.`); } Then(/^I see element "([^"]+)" does not exist$/, Then_I_see_element_does_not_exist); // =================================================================================== // ASSERTIONS: ELEMENT VISIBILITY (by Selector) // =================================================================================== /** * Asserts that an element matching the given selector is visible in the viewport. * * ```gherkin * Then I see element {string} is visible * ``` * * @param selector - The CSS selector of the element expected to be visible. * * @example * Then I see element ".main-content" is visible * * @remarks * This step uses Playwright's `expect(locator).toBeVisible()` which automatically waits * for the element to become visible. * @category Assertion Steps */ export async function Then_I_see_element_is_visible(this: CustomWorld, selector: string) { const locator = this.page.locator(selector); await expect(locator).toBeVisible({ timeout: 5000 }); this.log?.(`✅ Verified element "${selector}" is visible.`); } Then(/^I see element "([^"]+)" is visible$/, Then_I_see_element_is_visible); /** * Asserts that an element matching the given selector is NOT visible in the viewport. * * ```gherkin * Then I see element {string} is not visible * ``` * * @param selector - The CSS selector of the element expected NOT to be visible. * * @example * Then I see element ".modal-overlay" is not visible * * @remarks * This step uses Playwright's `expect(locator).not.toBeVisible()` which automatically waits * for the element to become hidden. * @category Assertion Steps */ export async function Then_I_see_element_is_not_visible(this: CustomWorld, selector: string) { const locator = this.page.locator(selector); await expect(locator).not.toBeVisible({ timeout: 5000 }); this.log?.(`✅ Verified element "${selector}" is NOT visible.`); } Then(/^I see element "([^"]+)" is not visible$/, Then_I_see_element_is_not_visible); // =================================================================================== // ASSERTIONS: ATTRIBUTE VALUES // =================================================================================== /** * Asserts that an element matching the given selector has a specific attribute with an exact value. * * ```gherkin * Then I see element {string} attribute {string} equals {string} * ``` * * @param selector - The CSS selector of the element to check. * @param attribute - The name of the attribute (e.g., "id", "class", "data-test"). * @param expectedValue - The exact expected value of the attribute. * * @example * Then I see element ".submit-button" attribute "disabled" equals "true" * * @remarks * This step uses Playwright's `expect(locator).toHaveAttribute()`. * @category Attribute Assertion Steps */ export async function Then_I_see_element_attribute_equals( this: CustomWorld, selector: string, attribute: string, expectedValue: string ) { const locator = this.page.locator(selector); await expect(locator).toHaveAttribute(attribute, expectedValue, { timeout: 5000 }); this.log?.( `✅ Verified element "${selector}" has attribute "${attribute}" equal to "${expectedValue}".` ); } Then( /^I see element "([^"]+)" attribute "([^"]+)" equals "(.*)"$/, Then_I_see_element_attribute_equals ); /** * Asserts that the previously stored element has a specific attribute with an exact value. * * ```gherkin * Then I see element attribute {string} equals {string} * ``` * * @param attr - The name of the attribute to check. * @param expectedValue - The exact expected value of the attribute. * * @example * When I find element by selector "input[name='rememberMe']" * Then I see element attribute "checked" equals "checked" * * @remarks * This step requires a preceding step that sets the {@link CustomWorld.element | current element}. * It uses Playwright's `expect(locator).toHaveAttribute()`. * @category Attribute Assertion Steps */ export async function Then_I_see_stored_element_attribute_equals( this: CustomWorld, attr: string, expectedValue: string ) { if (!this.element) { throw new Error( "No element is currently selected. Use a 'find' step before asserting its attributes." ); } await expect(this.element).toHaveAttribute(attr, expectedValue, { timeout: 5000 }); this.log?.(`✅ Verified stored element has attribute "${attr}" equal to "${expectedValue}".`); } Then( 'I see element attribute "{word}" equals {string}', Then_I_see_stored_element_attribute_equals ); /** * Asserts that the previously stored element has a specific attribute, regardless of its value. * * ```gherkin * Then I see element has attribute {string} * ``` * * @param attr - The name of the attribute expected to exist. * * @example * When I find element by selector "img.user-avatar" * Then I see element has attribute "alt" * * @remarks * This step requires a preceding step that sets the {@link CustomWorld.element | current element}. * It retrieves the attribute's value and asserts that it's not `null` (meaning the attribute is present). * @category Attribute Assertion Steps */ export async function Then_I_see_stored_element_has_attribute(this: CustomWorld, attr: string) { if (!this.element) throw new Error("No element stored in context to check for attribute."); // Use Playwright's expect.toHaveAttribute for robust checking of existence (value can be empty string, but not null) // For simply checking existence, we can assert that the attribute is not null or undefined. const attributeValue = await this.element.getAttribute(attr, { timeout: 5000 }); expect(attributeValue).not.toBeNull(); this.log?.(`✅ Verified stored element has attribute "${attr}".`); } Then("I see element has attribute {string}", Then_I_see_stored_element_has_attribute); /** * Asserts that the previously stored element's specific attribute contains a given substring. * * ```gherkin * Then I see element attribute {string} contains {string} * ``` * * @param attr - The name of the attribute to check. * @param part - The substring expected to be contained within the attribute's value. * * @example * When I find element by selector ".product-image" * Then I see element attribute "src" contains "thumbnail" * * @remarks * This step requires a preceding step that sets the {@link CustomWorld.element | current element}. * It retrieves the attribute's value and asserts that it includes the `part` substring. * @category Attribute Assertion Steps */ export async function Then_I_see_stored_element_attribute_contains( this: CustomWorld, attr: string, part: string ) { if (!this.element) throw new Error("No element stored in context to check attribute content."); // Use Playwright's expect.toHaveAttribute with a regex for 'contains' check await expect(this.element).toHaveAttribute(attr, new RegExp(part), { timeout: 5000 }); this.log?.(`✅ Verified stored element attribute "${attr}" contains "${part}".`); } Then( 'I see element attribute "{word}" contains {string}', Then_I_see_stored_element_attribute_contains ); /** * Asserts that an element matching the given selector has a specific attribute containing a given substring. * * ```gherkin * Then I see element {string} attribute {string} contains {string} * ``` * * @param selector - The CSS selector of the element to check. * @param attribute - The name of the attribute. * @param substring - The substring expected to be contained within the attribute's value. * * @example * Then I see element "a.download-link" attribute "href" contains ".pdf" * * @remarks * This step retrieves the attribute's value from the element matching the selector * and asserts that it includes the `substring`. * @category Attribute Assertion Steps */ export async function Then_I_see_element_attribute_contains( this: CustomWorld, selector: string, attribute: string, substring: string ) { const locator = this.page.locator(selector); // Use Playwright's expect.toHaveAttribute with a regex for 'contains' check await expect(locator).toHaveAttribute(attribute, new RegExp(substring), { timeout: 5000 }); this.log?.(`✅ Verified element "${selector}" attribute "${attribute}" contains "${substring}".`); } Then( /^I see element "([^"]+)" attribute "([^"]+)" contains "(.*)"$/, Then_I_see_element_attribute_contains ); /** * Asserts that an element matching the given selector has a specific attribute, regardless of its value. * * ```gherkin * Then I see element {string} has attribute {string} * ``` * * @param selector - The CSS selector of the element to check. * @param attribute - The name of the attribute expected to exist. * * @example * Then I see element "img.avatar" has attribute "src" * * @remarks * This step retrieves the attribute's value from the element matching the selector * and asserts that it's not `null` (meaning the attribute is present). * @category Attribute Assertion Steps */ export async function Then_I_see_element_has_attribute( this: CustomWorld, selector: string, attribute: string ) { const locator = this.page.locator(selector); // Playwright's toHaveAttribute with an empty string or regex can assert existence effectively. // toHaveAttribute(attr, /.+/) ensures it exists and has *some* non-empty value. // For just existence, checking if getAttribute is not null is explicit. const attributeValue = await locator.getAttribute(attribute, { timeout: 5000 }); expect(attributeValue).not.toBeNull(); this.log?.(`✅ Verified element "${selector}" has attribute "${attribute}".`); } Then(/^I see element "([^"]+)" has attribute "([^"]+)"$/, Then_I_see_element_has_attribute);