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.

402 lines (401 loc) 17.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Then_I_count_elements = Then_I_count_elements; exports.Then_I_see_button = Then_I_see_button; exports.Then_I_do_not_see_button = Then_I_do_not_see_button; exports.Then_I_see_text = Then_I_see_text; exports.Then_I_see_visible_text = Then_I_see_visible_text; exports.Then_I_do_not_see_visible_text = Then_I_do_not_see_visible_text; exports.Then_I_see_value = Then_I_see_value; exports.Then_I_do_not_see_value = Then_I_do_not_see_value; exports.Then_I_do_not_see_text = Then_I_do_not_see_text; exports.Then_I_see_text_in_the_element = Then_I_see_text_in_the_element; exports.Then_I_see_alias_in_the_element = Then_I_see_alias_in_the_element; exports.Then_I_see_button_is_disabled = Then_I_see_button_is_disabled; const cucumber_1 = require("@cucumber/cucumber"); const test_1 = require("@playwright/test"); const fakerUtils_1 = require("../helpers/utils/fakerUtils"); // Assuming this path is correct // =================================================================================== // ASSERTIONS: ELEMENT COUNT // =================================================================================== /** * Asserts that the previously stored collection of elements has an exact expected count. * * ```gherkin * Then I count {int} elements * ``` * * @param expectedCount - The expected number of elements in the collection. * * @example * Given I find elements by selector ".list-item" * Then I count 5 elements * * @remarks * This step requires a preceding step that populates {@link CustomWorld.elements | this.elements} * (e.g., "When I find elements by selector"). It then asserts that the number of * elements in that collection matches `expectedCount`. It also waits for `networkidle` * to ensure all elements that might affect the count have loaded. * @category Assertion Steps */ async function Then_I_count_elements(expectedCount) { if (!this.elements) throw new Error("No element collection found to count. Use a 'find elements' step first."); const count = await this.elements.count(); await this.page.waitForLoadState("networkidle"); // Wait for network to settle before asserting count (0, test_1.expect)(count).toBe(expectedCount); this.log?.(`✅ Verified element count: Expected ${expectedCount}, Found ${count}.`); } (0, cucumber_1.Then)("I count {int} elements", Then_I_count_elements); // =================================================================================== // ASSERTIONS: BUTTON VISIBILITY // =================================================================================== /** * Asserts that a button with the given text (or text from an alias) is visible on the page. * The text matching is case-insensitive and can be partial. * * ```gherkin * Then I see button {string} * ``` * * @param rawText - The text of the button, or an alias prefixed with "@" (e.g., "Submit", "@submitButtonLabel"). * * @example * Then I see button "Sign In" * Then I see button "@myLoginButton" * * @remarks * This step uses `page.getByRole("button", { name: ..., exact: false })`. * It waits for the page to be network idle and then asserts that the button is visible. * @category Assertion Steps */ async function Then_I_see_button(rawText) { let buttonText = rawText.startsWith("@") ? this.data[rawText.slice(1)] : rawText; if (!buttonText) { throw new Error(`No value found for alias: "${rawText}". Cannot assert button visibility.`); } const button = this.page.getByRole("button", { name: buttonText, exact: false, // Allows partial match, e.g., "Submit" finds "Submit Form" }); await this.page.waitForLoadState("networkidle"); // Wait for network to settle await (0, test_1.expect)(button).toBeVisible({ timeout: 5000 }); // Assert visibility with a timeout this.log?.(`✅ Verified button "${buttonText}" is visible.`); } (0, cucumber_1.Then)(/^I see button "(.*)"$/, Then_I_see_button); /** * Asserts that a button with the given text (or text from an alias) is NOT visible on the page. * The text matching is case-insensitive and can be partial. * * ```gherkin * Then I do not see button {string} * ``` * * @param rawText - The text of the button, or an alias prefixed with "@". * * @example * Then I do not see button "Delete Account" * Then I do not see button "@hiddenAdminButton" * * @remarks * This step checks for the absence of a visible button. It first waits for the page * to be network idle, then finds potential buttons by role and name. If any matching * button is found and is visible, the step will fail. * @category Assertion Steps */ async function Then_I_do_not_see_button(rawText) { let buttonText = rawText.startsWith("@") ? this.data[rawText.slice(1)] : rawText; if (!buttonText) { throw new Error(`No value found for alias: "${rawText}". Cannot assert button non-visibility.`); } const button = this.page.getByRole("button", { name: buttonText, exact: false, }); await this.page.waitForLoadState("networkidle"); // Wait for network to settle // Check if *any* matching button is visible. If so, throw an error. await (0, test_1.expect)(button).not.toBeVisible({ timeout: 5000 }); // Playwright's native assertion is more robust here this.log?.(`✅ Verified button "${buttonText}" is not visible.`); } (0, cucumber_1.Then)(/^I do not see button "(.*)"$/, Then_I_do_not_see_button); // =================================================================================== // ASSERTIONS: TEXT VISIBILITY // =================================================================================== /** * Asserts that specific text is visible on the current page or within the current frame/scope. * * ```gherkin * Then I see text {string} * ``` * * @param expectedText - The text string expected to be visible. * * @example * Then I see text "Welcome to your Dashboard" * * @remarks * This step uses `locator.waitFor({ state: "visible" })` to ensure the text is present * and displayed within the current Playwright scope (main page or active iframe). * Text matching is a substring match by default. * @category Assertion Steps */ async function Then_I_see_text(expectedText) { const scope = this.getScope(); // Supports iframe OR main page const locator = scope.locator(`text=${expectedText}`); // Playwright's text locator is robust // Use Playwright's expect for robust waiting and assertion await (0, test_1.expect)(locator).toBeVisible({ timeout: 5000 }); this.log?.(`✅ Verified text visible: "${expectedText}".`); } (0, cucumber_1.Then)("I see text {string}", Then_I_see_text); /** * Asserts that the exact visible text is present on the page. * This is similar to "I see text", but emphasizes "visible" for clarity. * * ```gherkin * Then I see visible text {string} * ``` * * @param text - The exact text string expected to be visible. * * @example * Then I see visible text "Dashboard" * * @remarks * This step uses `:text-is()` pseudo-class for exact text matching and `isVisible()` * to confirm presence. It also waits for `networkidle` beforehand. * Consider consolidating with `Then I see text {string}` if you prefer `toBeVisible` * which handles exact matching via options or `text-is` more flexibly. * @category Assertion Steps */ async function Then_I_see_visible_text(text) { await this.page.waitForLoadState("networkidle"); // Wait for network to settle const locator = this.page.locator(`:text-is("${text}")`); // Use Playwright's expect for robust waiting and assertion await (0, test_1.expect)(locator).toBeVisible({ timeout: 5000 }); this.log?.(`✅ Verified exact visible text: "${text}".`); } (0, cucumber_1.Then)("I see visible text {string}", Then_I_see_visible_text); /** * Asserts that specific exact visible text is NOT present on the page. * * ```gherkin * Then I do not see visible text {string} * ``` * * @param text - The exact text string expected NOT to be visible. * * @example * Then I do not see visible text "Logout" * * @remarks * This step uses `:text-is()` for exact text matching. It asserts that no element * with this exact text is visible. * @category Assertion Steps */ async function Then_I_do_not_see_visible_text(text) { const locator = this.page.locator(`:text-is("${text}")`); // Use Playwright's expect for robust assertion await (0, test_1.expect)(locator).not.toBeVisible({ timeout: 5000 }); this.log?.(`✅ Verified exact visible text NOT present: "${text}".`); } (0, cucumber_1.Then)("I do not see visible text {string}", Then_I_do_not_see_visible_text); // =================================================================================== // ASSERTIONS: ELEMENT VALUE // =================================================================================== /** * Asserts that the previously selected element has a specific input value. * * ```gherkin * Then I see value {string} * ``` * * @param expectedValue - The expected exact value of the input or textarea. * * @example * When I find element by selector "input[name='email']" * Then I see value "test@example.com" * * @remarks * This step requires a preceding step that sets the {@link CustomWorld.element | current element} * to an input, textarea, or other element that has an input value. * It uses Playwright's `locator.inputValue()`. * @category Assertion Steps */ async function Then_I_see_value(expectedValue) { if (!this.element) throw new Error("No element selected to check its value."); // Use Playwright's expect.toHaveValue for robust assertion await (0, test_1.expect)(this.element).toHaveValue(expectedValue, { timeout: 5000 }); this.log?.(`✅ Verified element has value: "${expectedValue}".`); } (0, cucumber_1.Then)("I see value {string}", Then_I_see_value); /** * Asserts that the previously selected element does NOT have a specific input value. * * ```gherkin * Then I do not see value {string} * ``` * * @param unwantedValue - The value that is expected NOT to be present in the input or textarea. * * @example * When I find element by selector "input[name='password']" * Then I do not see value "admin123" * * @remarks * This step requires a preceding step that sets the {@link CustomWorld.element | current element}. * It asserts that the element's current input value does not match `unwantedValue`. * @category Assertion Steps */ async function Then_I_do_not_see_value(unwantedValue) { if (!this.element) throw new Error("No element selected to check its value."); // Use Playwright's expect.not.toHaveValue for robust assertion await (0, test_1.expect)(this.element).not.toHaveValue(unwantedValue, { timeout: 5000 }); this.log?.(`✅ Verified element does NOT have value: "${unwantedValue}".`); } (0, cucumber_1.Then)("I do not see value {string}", Then_I_do_not_see_value); // =================================================================================== // ASSERTIONS: TEXT PRESENCE (Absence) // =================================================================================== /** * Asserts that specific text is NOT present on the page. This checks for complete absence, * not just visibility. * * ```gherkin * Then I do not see text {string} * ``` * * @param unexpectedText - The text string that is expected NOT to be found on the page. * * @example * Then I do not see text "Error Message" * * @remarks * This step uses `page.getByText` with `exact: true` and then asserts that the count * of matching elements is 0. This confirms the text is entirely absent from the DOM. * @category Assertion Steps */ async function Then_I_do_not_see_text(unexpectedText) { const el = this.page.getByText(unexpectedText, { exact: true }); await (0, test_1.expect)(el).toHaveCount(0); // This directly asserts that no such element exists this.log?.(`✅ Verified text NOT present in DOM: "${unexpectedText}".`); } (0, cucumber_1.Then)(/^I do not see text "(.*)"$/, Then_I_do_not_see_text); // =================================================================================== // ASSERTIONS: TEXT IN ELEMENT (with Alias/Faker) // =================================================================================== /** * Asserts that the previously selected element contains the given text, * which can be a literal string, an alias, or a Faker.js expression. * * ```gherkin * Then I see {string} in the element * ``` * * @param expected - The text string, alias (prefixed with "@"), or Faker.js expression expected to be contained within the element's text content. * * @example * When I find element by selector "#welcome-message" * Then I see "Welcome, John Doe!" in the element * Given I store "user.name" as "loggedInUserName" * When I find element by selector "#user-profile-name" * Then I see "@loggedInUserName" in the element * Then I see "Hello, {{person.firstName}}!" in the element * * @remarks * This step requires a preceding step that sets the {@link CustomWorld.element | current element}. * It resolves aliases and Faker expressions before comparing the `textContent` of the element. * It uses `expect(textContent).toContain(expected)` for partial matching. * @category Assertion Steps */ async function Then_I_see_text_in_the_element(expected) { const element = this.element; if (!element) throw new Error("No element selected to check its text content."); // ✅ Resolve alias if (expected.startsWith("@")) { const alias = expected.substring(1); expected = this.data[alias]; if (!expected) throw new Error(`No data stored for alias "@${alias}".`); } // ✅ Resolve faker syntax expected = (0, fakerUtils_1.evaluateFaker)(expected); // Use Playwright's expect.toContainText for robust assertion on visible text await (0, test_1.expect)(element).toContainText(expected, { timeout: 5000 }); this.log?.(`✅ Verified "${expected}" is contained in element text.`); } (0, cucumber_1.Then)("I see {string} in the element", Then_I_see_text_in_the_element); /** * Asserts that the previously selected element contains the value retrieved from a specific alias. * * ```gherkin * Then I see @{word} in the element * ``` * * @param alias - The alias name from which to retrieve the expected text value. * * @example * Given I store "Generated Name" as "tempName" * When I find element by selector "#display-name" * Then I see @tempName in the element * * @remarks * This step requires a preceding step that sets the {@link CustomWorld.element | current element}. * It fetches the value from `this.data[alias]` and then asserts that the element's * `textContent` (trimmed) contains this stored value. This is a specialized version of * `Then I see {string} in the element` specifically for aliases. * @category Assertion Steps */ async function Then_I_see_alias_in_the_element(alias) { const storedValue = this.data[alias]; if (storedValue === undefined || storedValue === null) { throw new Error(`No value found in data storage under alias "@${alias}". Alias might be undefined or null.`); } if (!this.element) { throw new Error("No element selected to check its text content. You must get an element before asserting its contents."); } // Use Playwright's expect.toContainText for robust assertion // Convert storedValue to string for reliable comparison await (0, test_1.expect)(this.element).toContainText(String(storedValue), { timeout: 5000 }); this.log?.(`✅ Verified element contains value from "@${alias}" ("${storedValue}").`); } (0, cucumber_1.Then)("I see @{word} in the element", Then_I_see_alias_in_the_element); // =================================================================================== // ASSERTIONS: BUTTON STATE // =================================================================================== /** * Asserts that a button with the given text (or text from an alias) is disabled. * * ```gherkin * Then I see button {string} is disabled * ``` * * @param rawText - The text of the button, or an alias prefixed with "@". * * @example * Then I see button "Submit" is disabled * Then I see button "@checkoutButton" is disabled * * @remarks * This step first locates the button by its role and name, asserts it's visible, * and then checks its disabled state using Playwright's `isDisabled()` method. * @category Assertion Steps */ async function Then_I_see_button_is_disabled(rawText) { // Resolve alias let buttonText = rawText.startsWith("@") ? this.data[rawText.slice(1)] : rawText; if (!buttonText) { throw new Error(`No value found for alias: "${rawText}". Cannot check button disabled state.`); } const button = this.page.getByRole("button", { name: buttonText, exact: false, }); // Assert visibility first, then disabled state await (0, test_1.expect)(button).toBeVisible({ timeout: 5000 }); await (0, test_1.expect)(button).toBeDisabled({ timeout: 5000 }); // Playwright's direct assertion is best this.log?.(`✅ Verified button "${buttonText}" is disabled.`); } (0, cucumber_1.Then)("I see button {string} is disabled", Then_I_see_button_is_disabled);