UNPKG

@progress/kendo-e2e

Version:

Kendo UI end-to-end test utilities.

495 lines 24 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()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WebApp = void 0; const selenium_webdriver_1 = require("selenium-webdriver"); const conditions_1 = require("./conditions"); const expect_1 = require("./expect"); const rgb2hex_1 = __importDefault(require("rgb2hex")); /** * This class encapsulates common location and interaction functionality over a {@link ThenableWebDriver}. */ class WebApp { constructor(driver) { this.driver = driver; } find(locator_1) { return __awaiter(this, arguments, void 0, function* (locator, { timeout = 10000, pollTimeout = 25 } = {}) { const errorMessage = `Failed to find element located by ${locator}.`; if (locator instanceof selenium_webdriver_1.By) { return yield this.driver.wait(selenium_webdriver_1.until.elementLocated(locator), timeout, errorMessage, pollTimeout); } else { return yield this.driver.wait(selenium_webdriver_1.until.elementLocated(selenium_webdriver_1.By.css(locator)), timeout, errorMessage, pollTimeout); } }); } findAll(locator) { return __awaiter(this, void 0, void 0, function* () { if (locator instanceof selenium_webdriver_1.By) { return yield this.driver.findElements(locator); } else { return yield this.driver.findElements(selenium_webdriver_1.By.css(locator)); } }); } findAllWithTimeout(locator_1) { return __awaiter(this, arguments, void 0, function* (locator, { timeout = 10000, pollTimeout = 25 } = {}) { const byLocator = locator instanceof selenium_webdriver_1.By ? locator : selenium_webdriver_1.By.css(locator); const start = Date.now(); let elements = []; while ((Date.now() - start) < timeout) { elements = yield this.driver.findElements(byLocator); if (elements.length > 0) { return elements; } yield this.driver.sleep(pollTimeout); } // Final attempt after timeout elements = yield this.driver.findElements(byLocator); return elements; }); } findChild(rootElement_1, locator_1) { return __awaiter(this, arguments, void 0, function* (rootElement, locator, { waitForChild = true, timeout = 10000, pollTimeout = 25 } = {}) { if (!(rootElement instanceof selenium_webdriver_1.WebElement)) { rootElement = yield this.find(rootElement); } if (waitForChild) { const message = `Failed to find child element located by ${locator}.`; yield this.wait(conditions_1.EC.hasChild(rootElement, locator), { timeout: timeout, message: message, pollTimeout: pollTimeout }); } return (locator instanceof selenium_webdriver_1.By) ? rootElement.findElement(locator) : rootElement.findElement(selenium_webdriver_1.By.css(locator)); }); } findChildren(rootElement_1, locator_1) { return __awaiter(this, arguments, void 0, function* (rootElement, locator, { waitForChild = true, timeout = 10000, pollTimeout = 25 } = {}) { if (!(rootElement instanceof selenium_webdriver_1.WebElement)) { rootElement = yield this.find(rootElement); } if (waitForChild) { const message = `Failed to find child element located by ${locator}.`; yield this.wait(conditions_1.EC.hasChild(rootElement, locator), { timeout: timeout, message: message, pollTimeout: pollTimeout }); } return (locator instanceof selenium_webdriver_1.By) ? rootElement.findElements(locator) : rootElement.findElements(selenium_webdriver_1.By.css(locator)); }); } click(element_1) { return __awaiter(this, arguments, void 0, function* (element, { timeout = 10000, pollTimeout = 25 } = {}) { try { if (!(element instanceof selenium_webdriver_1.WebElement)) { element = yield this.find(element, { timeout: timeout, pollTimeout: pollTimeout }); } yield element.click(); } catch (_a) { if (!(element instanceof selenium_webdriver_1.WebElement)) { element = yield this.find(element, { timeout: timeout, pollTimeout: pollTimeout }); } const notVisibleMessage = (element instanceof selenium_webdriver_1.WebElement) ? `Element located is not visible.` : `Element located by ${element} is not visible.`; const notEnabledMessage = (element instanceof selenium_webdriver_1.WebElement) ? `Element located is not visible.` : `Element located by ${element} is not visible.`; yield this.wait(selenium_webdriver_1.until.elementIsVisible(element), { timeout: timeout, message: notVisibleMessage }); yield this.wait(selenium_webdriver_1.until.elementIsEnabled(element), { timeout: timeout, message: notEnabledMessage }); yield element.click(); } }); } hover(element_1) { return __awaiter(this, arguments, void 0, function* (element, { timeout = 10000, pollTimeout = 25 } = {}) { if (!(element instanceof selenium_webdriver_1.WebElement)) { element = yield this.find(element, { timeout: timeout, pollTimeout: pollTimeout }); } const actions = this.driver.actions({ async: true, bridge: true }); yield actions.move({ origin: element }).perform(); }); } focus(element_1) { return __awaiter(this, arguments, void 0, function* (element, { timeout = 10000, pollTimeout = 25 } = {}) { if (!(element instanceof selenium_webdriver_1.WebElement)) { element = yield this.find(element, { timeout: timeout, pollTimeout: pollTimeout }); } yield this.driver.executeScript(`arguments[0].focus();`, element); yield this.driver.sleep(50); }); } contextClick(element_1) { return __awaiter(this, arguments, void 0, function* (element, { timeout = 10000, pollTimeout = 25 } = {}) { if (!(element instanceof selenium_webdriver_1.WebElement)) { element = yield this.find(element, { timeout: timeout, pollTimeout: pollTimeout }); } const actions = this.driver.actions({ async: true, bridge: true }); yield actions.contextClick(element).perform(); }); } doubleClick(element_1) { return __awaiter(this, arguments, void 0, function* (element, { timeout = 10000, pollTimeout = 25 } = {}) { if (!(element instanceof selenium_webdriver_1.WebElement)) { element = yield this.find(element, { timeout: timeout, pollTimeout: pollTimeout }); } const actions = this.driver.actions({ async: true, bridge: true }); yield actions.doubleClick(element).perform(); }); } waitForAnimationAndClick(element_1) { return __awaiter(this, arguments, void 0, function* (element, { timeout = 10000, pollTimeout = 50 } = {}) { yield this.waitForAnimation(element, { timeout: timeout, pollTimeout: pollTimeout }); yield this.click(element, { timeout: timeout, pollTimeout: pollTimeout }); }); } scrollAndClick(element_1) { return __awaiter(this, arguments, void 0, function* (element, { timeout = 10000, pollTimeout = 25 } = {}) { if (!(element instanceof selenium_webdriver_1.WebElement)) { element = yield this.find(element, { timeout: timeout, pollTimeout: pollTimeout }); } yield this.driver.executeScript("arguments[0].scrollIntoView({ behavior: 'instant', block: 'center', inline: 'nearest' });", element); yield element.click(); }); } scrollIntoView(locator_1) { return __awaiter(this, arguments, void 0, function* (locator, { timeout = 10000, pollTimeout = 25 } = {}) { const element = yield this.find(locator, { timeout: timeout, pollTimeout: pollTimeout }); yield this.driver.executeScript("arguments[0].scrollIntoView({ behavior: 'instant', block: 'center', inline: 'nearest' });", element); }); } dragTo(source, target) { return __awaiter(this, void 0, void 0, function* () { let sourceElement; let targetElement; if (source instanceof selenium_webdriver_1.By) { sourceElement = yield this.find(source); } else { sourceElement = source; } if (target instanceof selenium_webdriver_1.By) { targetElement = yield this.find(target); } else { targetElement = target; } const actions = this.driver.actions({ async: true, bridge: true }); yield actions.dragAndDrop(sourceElement, targetElement).perform(); }); } dragByOffset(element, offsetX, offsetY) { return __awaiter(this, void 0, void 0, function* () { if (!(element instanceof selenium_webdriver_1.WebElement)) { element = yield this.find(element); } const actions = this.driver.actions({ async: true, bridge: true }); yield actions.dragAndDrop(element, { x: offsetX, y: offsetY }).perform(); }); } type(element_1, text_1) { return __awaiter(this, arguments, void 0, function* (element, text, { clear = true, sendEnter = false } = {}) { if (!(element instanceof selenium_webdriver_1.WebElement)) { element = yield this.find(element); } if (clear) { yield element.clear(); } yield element.sendKeys(text); if (sendEnter) { yield this.sendKey(selenium_webdriver_1.Key.ENTER); } }); } sendKey(key) { return __awaiter(this, void 0, void 0, function* () { yield this.driver.actions({ async: true, bridge: true }).sendKeys(key).perform(); }); } sendKeyCombination(key1, key2) { return __awaiter(this, void 0, void 0, function* () { yield this.sendKeysCombination([key1, key2]); }); } sendKeysCombination(keys) { return __awaiter(this, void 0, void 0, function* () { const actions = this.driver.actions({ async: false, bridge: true }); for (const key of keys) { actions.keyDown(key).pause(10); } for (const key of keys.reverse()) { actions.keyUp(key).pause(10); } yield actions.perform(); }); } sendControlKeyCombination(key) { return __awaiter(this, void 0, void 0, function* () { const control = (process.platform === 'darwin' ? selenium_webdriver_1.Key.COMMAND : selenium_webdriver_1.Key.CONTROL); yield this.sendKeysCombination([control, key]); }); } isVisible(element_1) { return __awaiter(this, arguments, void 0, function* (element, { timeout = 10000, pollTimeout = 25 } = {}) { return yield this.waitSafely(conditions_1.EC.isVisible(element), { timeout: timeout, pollTimeout: pollTimeout }); }); } isNotVisible(element_1) { return __awaiter(this, arguments, void 0, function* (element, { timeout = 10000, pollTimeout = 25 } = {}) { return yield this.waitSafely(conditions_1.EC.notVisible(element), { timeout: timeout, pollTimeout: pollTimeout }); }); } isInViewport(element_1) { return __awaiter(this, arguments, void 0, function* (element, { timeout = 10000, pollTimeout = 25 } = {}) { return yield this.waitSafely(conditions_1.EC.isInViewport(element), { timeout: timeout, pollTimeout: pollTimeout }); }); } isNotInViewport(element_1) { return __awaiter(this, arguments, void 0, function* (element, { timeout = 10000, pollTimeout = 25 } = {}) { return yield this.waitSafely(conditions_1.EC.notInViewport(element), { timeout: timeout, pollTimeout: pollTimeout }); }); } hasFocus(element) { return __awaiter(this, void 0, void 0, function* () { return (element instanceof selenium_webdriver_1.WebElement) ? yield this.waitSafely(conditions_1.EC.hasFocus(element)) : yield this.waitSafely(conditions_1.EC.hasFocus(yield this.find(element))); }); } hasNoFocus(element) { return __awaiter(this, void 0, void 0, function* () { return (element instanceof selenium_webdriver_1.WebElement) ? yield this.waitSafely(conditions_1.EC.hasNoFocus(element)) : yield this.waitSafely(conditions_1.EC.hasNoFocus(yield this.find(element))); }); } hasText(element, text) { return __awaiter(this, void 0, void 0, function* () { return (element instanceof selenium_webdriver_1.WebElement) ? yield this.waitSafely(conditions_1.EC.hasText(element, text)) : yield this.waitSafely(conditions_1.EC.hasText(yield this.find(element), text)); }); } hasValue(element, value) { return __awaiter(this, void 0, void 0, function* () { return (element instanceof selenium_webdriver_1.WebElement) ? yield this.waitSafely(conditions_1.EC.hasValue(element, value)) : yield this.waitSafely(conditions_1.EC.hasValue(yield this.find(element), value)); }); } hasAttribute(element_1, attribute_1, value_1) { return __awaiter(this, arguments, void 0, function* (element, attribute, value, exactMatch = true) { return (element instanceof selenium_webdriver_1.WebElement) ? yield this.waitSafely(conditions_1.EC.hasAttribute(element, attribute, value, exactMatch)) : yield this.waitSafely(conditions_1.EC.hasAttribute(yield this.find(element), attribute, value, exactMatch)); }); } hasClass(element_1, value_1) { return __awaiter(this, arguments, void 0, function* (element, value, exactMatch = false) { return (element instanceof selenium_webdriver_1.WebElement) ? yield this.waitSafely(conditions_1.EC.hasClass(element, value, exactMatch)) : yield this.waitSafely(conditions_1.EC.hasClass(yield this.find(element), value, exactMatch)); }); } sleep(milliseconds) { return __awaiter(this, void 0, void 0, function* () { yield this.driver.sleep(milliseconds); }); } wait(condition_1) { return __awaiter(this, arguments, void 0, function* (condition, { timeout = 10000, message = 'Failed to satisfy condition.', pollTimeout = 25 } = {}) { yield this.driver.wait(condition, timeout, message, pollTimeout); }); } waitSafely(condition_1) { return __awaiter(this, arguments, void 0, function* (condition, { timeout = 10000, pollTimeout = 25 } = {}) { try { yield this.driver.wait(condition, timeout, null, pollTimeout); return true; } catch (_a) { return false; } }); } waitForAnimation(element_1) { return __awaiter(this, arguments, void 0, function* (element, { timeout = 10000, pollTimeout = 50 } = {}) { const locatorStringValue = (element instanceof selenium_webdriver_1.WebElement) ? 'element' : element; yield this.wait(conditions_1.EC.isVisible(element), { timeout: timeout, message: `Failed to find ${locatorStringValue}` }); const isElementStable = () => __awaiter(this, void 0, void 0, function* () { const rect = (element instanceof selenium_webdriver_1.WebElement) ? yield element.getRect() : yield (yield this.find(element)).getRect(); yield this.sleep(pollTimeout); const newRect = (element instanceof selenium_webdriver_1.WebElement) ? yield element.getRect() : yield (yield this.find(element)).getRect(); return (rect.x === newRect.x && rect.y === newRect.y && rect.width === newRect.width && rect.height === newRect.height); }); yield this.wait(isElementStable, { timeout: timeout, message: `Element ${locatorStringValue} is still moving or resizing.` }); }); } getScreenshot() { return __awaiter(this, void 0, void 0, function* () { return yield this.driver.takeScreenshot(); }); } executeScript(script) { return __awaiter(this, void 0, void 0, function* () { return yield this.driver.executeScript(script); }); } getText(element) { return __awaiter(this, void 0, void 0, function* () { if (!(element instanceof selenium_webdriver_1.WebElement)) { element = yield this.find(element); } try { return yield element.getText(); } catch (_a) { return undefined; } }); } getAttribute(element, attribute) { return __awaiter(this, void 0, void 0, function* () { if (!(element instanceof selenium_webdriver_1.WebElement)) { element = yield this.find(element); } return yield element.getAttribute(attribute); }); } getProperty(element, property) { return __awaiter(this, void 0, void 0, function* () { if (!(element instanceof selenium_webdriver_1.WebElement)) { element = yield this.find(element); } const script = function (element, property) { return element[property]; }; return yield this.driver.executeScript(script, element, property); }); } getColor(element) { return __awaiter(this, void 0, void 0, function* () { if (!(element instanceof selenium_webdriver_1.WebElement)) { element = yield this.find(element); } const color = yield element.getCssValue('color'); return (0, rgb2hex_1.default)(color).hex; }); } getBackgroundColor(element) { return __awaiter(this, void 0, void 0, function* () { if (!(element instanceof selenium_webdriver_1.WebElement)) { element = yield this.find(element); } const color = yield element.getCssValue('background-color'); return (0, rgb2hex_1.default)(color).hex; }); } /** * Hides the text caret either globally (all input & textarea elements) or for a specific element. * * When no element is provided, a <style> tag is injected that sets caret-color to transparent * for all input and textarea elements. This is reversible only by page reload or manually removing * the injected style element. * * When an element is provided (WebElement, By locator, or CSS selector string), the element is * located (if needed) and its caret color is set to transparent. * * @param element Optional element whose caret should be hidden (WebElement instance, By locator, or CSS selector string). * @param options Optional timeout and pollTimeout for element location. */ hideCursor(element_1) { return __awaiter(this, arguments, void 0, function* (element, { timeout = 10000, pollTimeout = 25 } = {}) { if (!element) { yield this.driver.executeScript(() => { const existing = document.head.querySelector('style[data-hide-caret="true"]'); if (existing) { return; } const style = document.createElement('style'); style.setAttribute('data-hide-caret', 'true'); style.textContent = 'input, textarea { caret-color: transparent !important; }'; document.head.appendChild(style); }); } else { if (!(element instanceof selenium_webdriver_1.WebElement)) { element = yield this.find(element, { timeout: timeout, pollTimeout: pollTimeout }); } yield this.driver.executeScript((el) => { if (el && el instanceof HTMLElement) { el.style.caretColor = 'transparent'; } }, element); } }); } /** * Creates an expectation API for the specified element selector. * This provides a fluent interface for asserting element states with automatic retry logic. * The expect API will continuously retry finding the element and checking the condition * until it passes or the timeout is reached (default: 3000ms). * * @param selector - CSS selector string or By locator to identify the element * @returns ExpectApi object with assertion methods * * @example * ```typescript * // Assert element has specific text (default 3s timeout) * await app.expect('#result').toHaveText('Welcome user'); * * // Assert element is visible * await app.expect('.modal').toBeVisible(); * * // Assert element is not visible * await app.expect('.spinner').not.toBeVisible(); * * // Assert with custom timeout and message * await app.expect('#message').toHaveText('Success', { * timeout: 5000, * message: 'Failed to load results.' * }); * * // Assert using regex pattern * await app.expect('#status').toHaveText(/completed|success/i, { timeout: 10000 }); * * // Assert element has value * await app.expect('#input').toHaveValue('expected value', { timeout: 2000 }); * * // Assert element has focus * await app.expect('#activeInput').toHaveFocus(); * * // Assert element has attribute * await app.expect('#btn').toHaveAttribute('disabled', 'true'); * * // Assert element has class (partial match) * await app.expect('#div').toHaveClass('active', { exactMatch: false }); * ``` */ expect(selector) { const by = typeof selector === 'string' ? selenium_webdriver_1.By.css(selector) : selector; return (0, expect_1.expectSelector)(this.driver, by); } } exports.WebApp = WebApp; //# sourceMappingURL=web-app.js.map