UNPKG

@vibe/testkit

Version:
383 lines 17.4 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseElement = void 0; const test_1 = require("@playwright/test"); /** * Class representing a base element for Playwright tests. */ class BaseElement { /** * Create a BaseElement. * @param {Page} page - The Playwright page object. * @param {Locator} locator - The locator for the element. * @param {string} elementReportName - The name for reporting purposes. */ constructor(page, locator, elementReportName) { this.DEFAULT_TIMEOUT = 30000; // 30 seconds this.page = page; this.locator = locator; this.elementReportName = elementReportName; } /** * Get the page object. * @returns {Page} - The page object. */ getPage() { return this.page; } /** * Get the locator of the element. * @returns {Locator} - The locator of the element. */ getLocator() { return this.locator; } /** * Get the element report name. * @returns {string} - The element report name. */ getElementReportName() { return this.elementReportName; } /** * Hover the element. * @returns {Promise<void>} */ hover() { return __awaiter(this, void 0, void 0, function* () { yield test_1.test.step(`Hover ${this.getElementReportName()}`, () => __awaiter(this, void 0, void 0, function* () { yield this.getLocator().hover(); })); }); } /** * Click the element. * @returns {Promise<void>} */ click() { return __awaiter(this, void 0, void 0, function* () { yield test_1.test.step(`Click ${this.getElementReportName()}`, () => __awaiter(this, void 0, void 0, function* () { yield this.getLocator().click(); })); }); } /** * Get the text of the element. * @returns {Promise<string>} - The text of the element (empty string if only whitespace or empty, throws if all are null/undefined). */ getText() { return __awaiter(this, void 0, void 0, function* () { return yield test_1.test.step(`Get text of ${this.getElementReportName()}`, () => __awaiter(this, void 0, void 0, function* () { const texts = [ yield this.getLocator().innerText(), yield this.getLocator().textContent(), yield this.getAttributeValue("value") ]; // If all are null/undefined, throw error if (texts.every(value => value == null || value === undefined)) { throw new Error(`Could not retrieve text for ${this.getElementReportName()}: all texts are null/undefined`); } // Trim all string values, keep null/undefined as is const trimmed = texts.map(value => (typeof value === "string" ? value.trim() : value)); // Filter out null/undefined values const nonNullValues = trimmed.filter(value => value != null); // If all non-null are empty string, return "" if (nonNullValues.every(value => value === "")) { return ""; } // Otherwise, return the first non-empty string by priority const firstNonEmpty = nonNullValues.find(value => typeof value === "string" && value !== ""); if (typeof firstNonEmpty === "string") { return firstNonEmpty; } // Fallback: if only empty string(s) and null/undefined remain, return "" return ""; })); }); } /** * Scroll the element into view if needed. * @returns {Promise<void>} */ scrollIntoView() { return __awaiter(this, void 0, void 0, function* () { yield test_1.test.step(`Scroll ${this.getElementReportName()} into view`, () => __awaiter(this, void 0, void 0, function* () { yield this.getLocator().scrollIntoViewIfNeeded(); })); }); } /** * Get the value of an attribute of the element. * @param {string} attributeName - The name of the attribute. * @param {number} timeout - The timeout for the attribute value. Defaults to 30 seconds. * @returns {Promise<string | null>} - The value of the attribute. */ getAttributeValue(attributeName_1) { return __awaiter(this, arguments, void 0, function* (attributeName, timeout = this.DEFAULT_TIMEOUT) { return yield test_1.test.step(`Get attribute ${attributeName} of ${this.getElementReportName()}`, () => __awaiter(this, void 0, void 0, function* () { const attributeValue = yield this.getLocator().getAttribute(attributeName, { timeout }); if (attributeValue === null || attributeValue === undefined) { return ""; } return attributeValue; })); }); } /** * Wait for the element to be visible. * @param {number} timeout - The timeout for the element to be visible. Defaults to 30 seconds. * @returns {Promise<void>} */ waitForElementToBeVisible() { return __awaiter(this, arguments, void 0, function* (timeout = this.DEFAULT_TIMEOUT) { yield test_1.test.step(`Wait for ${this.getElementReportName()} to be visible`, () => __awaiter(this, void 0, void 0, function* () { yield this.getLocator().waitFor({ state: "visible", timeout }); })); }); } /** * Wait for the element to be hidden. * @param {number} timeout - The timeout for the element to be hidden. Defaults to 30 seconds. * @returns {Promise<void>} */ waitForElementToBeHidden() { return __awaiter(this, arguments, void 0, function* (timeout = this.DEFAULT_TIMEOUT) { yield test_1.test.step(`Wait for ${this.getElementReportName()} to be hidden`, () => __awaiter(this, void 0, void 0, function* () { yield this.getLocator().waitFor({ state: "hidden", timeout }); })); }); } /** * Wait for the element to be absent. * @param {number} timeout - The timeout for the element to be absent. Defaults to 30 seconds. * @returns {Promise<void>} */ waitForElementToBeDetached() { return __awaiter(this, arguments, void 0, function* (timeout = this.DEFAULT_TIMEOUT) { yield test_1.test.step(`Wait for ${this.getElementReportName()} to be absent`, () => __awaiter(this, void 0, void 0, function* () { yield this.getLocator().waitFor({ state: "detached", timeout }); })); }); } /** * Wait for the element to be attached. * @param {number} timeout - The timeout for the element to be attached. Defaults to 30 seconds. * @returns {Promise<void>} */ waitForElementToBeAttached() { return __awaiter(this, arguments, void 0, function* (timeout = this.DEFAULT_TIMEOUT) { yield test_1.test.step(`Wait for ${this.getElementReportName()} to be attached`, () => __awaiter(this, void 0, void 0, function* () { yield this.getLocator().waitFor({ state: "attached", timeout }); })); }); } /** * Count the number of elements matching the locator. * @returns {Promise<number>} - The number of elements matching the locator. */ count() { return __awaiter(this, void 0, void 0, function* () { return yield test_1.test.step(`Count elements matching ${this.getElementReportName()}`, () => __awaiter(this, void 0, void 0, function* () { return yield this.getLocator().count(); })); }); } /** * Check if the element is enabled. * @param {number} timeout - The timeout for the element to be enabled. Defaults to 30 seconds. * @returns {Promise<boolean>} - Returns true if the element is enabled, otherwise false. */ isEnabled() { return __awaiter(this, arguments, void 0, function* (timeout = this.DEFAULT_TIMEOUT) { return yield test_1.test.step(`Check if ${this.getElementReportName()} is enabled`, () => __awaiter(this, void 0, void 0, function* () { return yield this.getLocator().isEnabled({ timeout }); })); }); } /** * Check if the element is disabled. * @param {number} timeout - The timeout for the element to be disabled. Defaults to 30 seconds. * @returns {Promise<boolean>} - Returns true if the element is disabled, otherwise false. */ isDisabled() { return __awaiter(this, arguments, void 0, function* (timeout = this.DEFAULT_TIMEOUT) { return yield test_1.test.step(`Check if ${this.getElementReportName()} is disabled`, () => __awaiter(this, void 0, void 0, function* () { return yield this.getLocator().isDisabled({ timeout }); })); }); } /** * Check if the element is visible. * @param {number} timeout - The timeout for the element to be visible. Defaults to 30 seconds. * @returns {Promise<boolean>} - Returns true if the element is visible, otherwise false. */ isVisible() { return __awaiter(this, arguments, void 0, function* (timeout = this.DEFAULT_TIMEOUT) { return yield test_1.test.step(`Check if ${this.getElementReportName()} is visible`, () => __awaiter(this, void 0, void 0, function* () { return yield this.getLocator().isVisible({ timeout }); })); }); } /** * Check if the element is hidden. * @param {number} timeout - The timeout for the element to be hidden. Defaults to 30 seconds. * @returns {Promise<boolean>} - Returns true if the element is hidden, otherwise false. */ isHidden() { return __awaiter(this, arguments, void 0, function* (timeout = this.DEFAULT_TIMEOUT) { return yield test_1.test.step(`Check if ${this.getElementReportName()} is hidden`, () => __awaiter(this, void 0, void 0, function* () { return yield this.getLocator().isHidden({ timeout }); })); }); } /** * Remove focus from the element. * @returns {Promise<void>} */ removeFocus() { return __awaiter(this, void 0, void 0, function* () { yield test_1.test.step(`Remove focus from ${this.getElementReportName()}`, () => __awaiter(this, void 0, void 0, function* () { yield this.getPage().locator("body").click(); })); }); } /** * Get the computed style of an element. * @param {string} property - The property to get the computed style of. * @returns {Promise<string>} - The computed style of the element. */ getComputedStyle(property) { return __awaiter(this, void 0, void 0, function* () { return yield test_1.test.step(`Get computed style of ${property} for ${this.getElementReportName()}`, () => __awaiter(this, void 0, void 0, function* () { return yield this.getLocator().evaluate((el, property) => window.getComputedStyle(el).getPropertyValue(property), property); })); }); } /** * Check if the element is expanded. * @returns {Promise<boolean>} True if the element is expanded, false otherwise. */ isExpanded() { return __awaiter(this, void 0, void 0, function* () { return yield test_1.test.step(`Check if ${this.getElementReportName()} is expanded`, () => __awaiter(this, void 0, void 0, function* () { return (yield this.getAttributeValue("aria-expanded")) === "true"; })); }); } /** * Check if the element is checked. * @returns {Promise<boolean>} True if the element is checked, false otherwise. */ isChecked() { return __awaiter(this, void 0, void 0, function* () { return yield test_1.test.step(`Check if ${this.getElementReportName()} is checked`, () => __awaiter(this, void 0, void 0, function* () { return (yield this.getAttributeValue("aria-checked")) === "true"; })); }); } /** * Check if the element is selected. * @returns {Promise<boolean>} True if the element is selected, false otherwise. */ isSelected() { return __awaiter(this, void 0, void 0, function* () { return yield test_1.test.step(`Check if ${this.getElementReportName()} is selected`, () => __awaiter(this, void 0, void 0, function* () { return (yield this.getAttributeValue("aria-selected")) === "true"; })); }); } /** * Wait for the element to be in a certain state. * @param {Object} options - The options for the wait. * @returns {Promise<void>} * @deprecated Use waitForElementToBeVisible, waitForElementToBeHidden, waitForElementToBeDetached, waitForElementToBeAttached instead. */ waitFor() { return __awaiter(this, arguments, void 0, function* (options = {}) { yield test_1.test.step(`Wait for ${this.getElementReportName()}`, () => __awaiter(this, void 0, void 0, function* () { yield this.getLocator().waitFor(options); })); }); } /** * Wait for the element to be visible. * @returns {Promise<void>} * @deprecated Use waitForElementToBeVisible instead. */ waitForVisible() { return __awaiter(this, void 0, void 0, function* () { yield test_1.test.step(`Wait for ${this.getElementReportName()} to be visible`, () => __awaiter(this, void 0, void 0, function* () { yield this.getLocator().waitFor({ state: "visible" }); })); }); } /** * Wait for the element to be absent. * @returns {Promise<void>} * @deprecated Use waitForElementToBeDetached instead. */ waitForAbsence() { return __awaiter(this, void 0, void 0, function* () { yield test_1.test.step(`Wait for ${this.getElementReportName()} to be absent`, () => __awaiter(this, void 0, void 0, function* () { yield this.getLocator().waitFor({ state: "detached" }); })); }); } /** * Wait for the list elements to stabilize (i.e., the count of items remains constant for a specified duration). * @param {Locator} locator - The locator for the elements. * @returns {Promise<void>} * @deprecated */ waitForAndVerifyElements(locator) { return __awaiter(this, void 0, void 0, function* () { yield test_1.test.step(`Wait for ${this.getElementReportName()} items to stabilize and verify existence`, () => __awaiter(this, void 0, void 0, function* () { let previousCount = 0; let stableCountTime = 0; const stabilizationTimeMs = 500; // eslint-disable-next-line no-constant-condition while (true) { const currentCount = yield locator.count(); // Verify we have at least one element if (currentCount === 0) { yield this.getPage().waitForTimeout(100); continue; } // Check if all elements are visible const elements = yield locator.all(); const visibleStates = yield Promise.all(elements.map(el => el.isVisible())); const allVisible = visibleStates.every(state => state === true); if (!allVisible) { yield this.getPage().waitForTimeout(100); continue; } if (currentCount === previousCount) { stableCountTime += 100; } else { stableCountTime = 0; } if (stableCountTime >= stabilizationTimeMs) { break; } previousCount = currentCount; yield this.getPage().waitForTimeout(100); } if ((yield locator.count()) === 0) { throw new Error(`No ${this.getElementReportName()} elements found after stabilization`); } })); }); } } exports.BaseElement = BaseElement; //# sourceMappingURL=BaseElement.js.map