e2ed
Version:
E2E testing framework over Playwright
234 lines (233 loc) • 9.22 kB
JavaScript
"use strict";
/* eslint-disable max-lines, @typescript-eslint/naming-convention, @typescript-eslint/no-non-null-assertion */
Object.defineProperty(exports, "__esModule", { value: true });
exports.Selector = void 0;
const node_util_1 = require("node:util");
const internal_1 = require("../../constants/internal");
const frameContext_1 = require("../../context/frameContext");
const createLocator_1 = require("../../createLocator");
const useContext_1 = require("../../useContext");
const getAttributeCssSelector_1 = require("./getAttributeCssSelector");
const setRetryData = (promise, retryData) => {
// eslint-disable-next-line no-param-reassign
promise[internal_1.RETRY_KEY] = retryData;
};
function toJSON() {
return JSON.stringify(this);
}
/**
* Selector.
*/
class Selector {
description;
args;
cssString;
kind;
locator;
parameterAttributePrefix;
parentSelector;
testIdAttribute;
testIdSeparator;
constructor({ args, cssString, kind = 'css', parameterAttributePrefix, parentSelector, testIdAttribute, testIdSeparator, }) {
this.args = args;
this.cssString = cssString;
this.description =
kind === 'css' ? cssString : `${parentSelector.description}.${kind}(${args?.join(', ')})`;
this.kind = kind;
this.locator = (0, createLocator_1.createTestLocator)({
attributesOptions: { parameterAttributePrefix, testIdAttribute, testIdSeparator },
createLocatorByCssSelector: (selector) => selector,
supportWildcardsInCssSelectors: true,
}).locator;
this.parameterAttributePrefix = parameterAttributePrefix;
this.parentSelector = parentSelector;
this.testIdAttribute = testIdAttribute;
this.testIdSeparator = testIdSeparator;
}
get boundingClientRect() {
const result = this.getPlaywrightLocator()
.boundingBox()
.then((box) => {
const { height, width, x, y } = box ?? { height: 0, width: 0, x: 0, y: 0 };
const bottom = height + y;
const right = width + x;
return { bottom, height, left: x, right, toJSON, top: y, width, x, y };
});
setRetryData(result, { property: 'boundingClientRect', selector: this });
return result;
}
get checked() {
const result = this.getPlaywrightLocator()
.isChecked()
.catch(() => null);
setRetryData(result, { property: 'checked', selector: this });
return result;
}
get count() {
const result = this.getPlaywrightLocator().count();
setRetryData(result, { property: 'count', selector: this });
return result;
}
get exists() {
const result = this.getPlaywrightLocator()
.count()
.then((count) => count > 0);
setRetryData(result, { property: 'exists', selector: this });
return result;
}
get scrollHeight() {
const result = this.getPlaywrightLocator().evaluate((element) => element.scrollHeight);
setRetryData(result, { property: 'scrollHeight', selector: this });
return result;
}
get scrollLeft() {
const result = this.getPlaywrightLocator().evaluate((element) => element.scrollLeft);
setRetryData(result, { property: 'scrollLeft', selector: this });
return result;
}
get scrollTop() {
const result = this.getPlaywrightLocator().evaluate((element) => element.scrollTop);
setRetryData(result, { property: 'scrollTop', selector: this });
return result;
}
get scrollWidth() {
const result = this.getPlaywrightLocator().evaluate((element) => element.scrollWidth);
setRetryData(result, { property: 'scrollWidth', selector: this });
return result;
}
get textContent() {
const result = this.getPlaywrightLocator()
.textContent()
.then((content) => content ?? '');
setRetryData(result, { property: 'textContent', selector: this });
return result;
}
get value() {
const result = this.getPlaywrightLocator()
.inputValue()
.catch(() => null);
setRetryData(result, { property: 'value', selector: this });
return result;
}
get visible() {
const result = this.getPlaywrightLocator().isVisible();
setRetryData(result, { property: 'visible', selector: this });
return result;
}
static create({ cssString, parameterAttributePrefix, testIdAttribute, testIdSeparator, }) {
return new Selector({ cssString, parameterAttributePrefix, testIdAttribute, testIdSeparator });
}
createSelector(cssString) {
const { parameterAttributePrefix, testIdAttribute, testIdSeparator } = this;
return new Selector({ cssString, parameterAttributePrefix, testIdAttribute, testIdSeparator });
}
filter(cssSelectorString) {
return this.createChildSelector('filter', [cssSelectorString]);
}
filterByLocatorParameter(parameter, value) {
return this.filter((0, getAttributeCssSelector_1.getAttributeCssSelector)(this.getParameterAttribute(parameter), value));
}
filterByTestId(...args) {
return this.filter(this.locator(...args));
}
find(cssSelectorString) {
return this.createChildSelector('find', [cssSelectorString]);
}
findByLocatorParameter(parameter, value) {
return this.find((0, getAttributeCssSelector_1.getAttributeCssSelector)(this.getParameterAttribute(parameter), value));
}
findByTestId(...args) {
return this.find(this.locator(...args));
}
getAttribute(attributeName) {
const result = this.getPlaywrightLocator().getAttribute(attributeName);
setRetryData(result, { args: [attributeName], property: 'getAttribute', selector: this });
return result;
}
getLocatorParameter(parameter) {
return this.getAttribute(this.getParameterAttribute(parameter));
}
getPlaywrightLocator() {
const args = this.args;
const selector = this.parentSelector;
switch (this.kind) {
case 'css':
return ((0, frameContext_1.getFrameContext)() ?? (0, useContext_1.getPlaywrightPage)()).locator(this.cssString);
case 'filter':
return selector.getPlaywrightLocator().and((0, useContext_1.getPlaywrightPage)().locator(String(args[0])));
case 'find':
return selector
.getPlaywrightLocator()
.locator((0, useContext_1.getPlaywrightPage)().locator(String(args[0])));
case 'nth':
return args[0] === -1
? selector.getPlaywrightLocator().last()
: selector.getPlaywrightLocator().nth(Number(args[0]));
case 'parent':
return selector.getPlaywrightLocator().locator('xpath=..');
case 'withText':
return selector.getPlaywrightLocator().filter({ hasText: args[0] });
// no default
}
}
getStyleProperty(propertyName) {
const result = this.getPlaywrightLocator().evaluate((element, property) => getComputedStyle(element).getPropertyValue(property), propertyName);
setRetryData(result, { args: [propertyName], property: 'getStyleProperty', selector: this });
return result;
}
getTestId() {
return this.getAttribute(this.testIdAttribute);
}
hasAttribute(attributeName) {
const result = this.getPlaywrightLocator()
.getAttribute(attributeName)
.then((attribute) => typeof attribute === 'string');
setRetryData(result, { args: [attributeName], property: 'hasAttribute', selector: this });
return result;
}
hasLocatorParameter(parameter) {
return this.hasAttribute(this.getParameterAttribute(parameter));
}
hasTestId() {
return this.hasAttribute(this.testIdAttribute);
}
nth(index) {
return this.createChildSelector('nth', [index]);
}
parent() {
return this.createChildSelector('parent');
}
toJSON() {
return { description: this.description };
}
/**
* Custom string presentation of selector.
*/
toString() {
return `Selector for ${this.description}`;
}
withText(textOrRegExp) {
return this.createChildSelector('withText', [textOrRegExp]);
}
createChildSelector(kind, args) {
const { cssString, parameterAttributePrefix, testIdAttribute, testIdSeparator } = this;
return new Selector({
args,
cssString,
kind,
parameterAttributePrefix,
parentSelector: this,
testIdAttribute,
testIdSeparator,
});
}
getParameterAttribute(parameter) {
return this.parameterAttributePrefix + parameter;
}
}
exports.Selector = Selector;
/**
* Custom presentation of selector for `nodejs` `inspect`.
*/
// eslint-disable-next-line @typescript-eslint/unbound-method
Selector.prototype[node_util_1.inspect.custom] = Selector.prototype.toString;