@progress/kendo-e2e
Version:
Kendo UI end-to-end test utilities.
495 lines • 24 kB
JavaScript
"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