mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
* [services/lib/web_element_wrapper] use Generics in replyCall * [services/lib/web_element_wrapper] remove redundant return types * [services/lib/web_element_wrapper/] set retryCall timeout to 200 ms * [services/find] explcitly pass element to have locator===null by default * use static method to create WebElementWrapper * missed a couple uses * move some values to constants * remove some unnecessary type info
This commit is contained in:
parent
39bab79bca
commit
f41db0bd42
3 changed files with 245 additions and 125 deletions
|
@ -185,8 +185,8 @@ export async function BrowserProvider({ getService }: FtrProviderContext) {
|
|||
* @return {Promise<void>}
|
||||
*/
|
||||
public async dragAndDrop(
|
||||
from: { offset: { x: any; y: any }; location: { _webElement: any } },
|
||||
to: { offset: { x: any; y: any }; location: { _webElement: any; x: any } }
|
||||
from: { offset: { x: any; y: any }; location: any },
|
||||
to: { offset: { x: any; y: any }; location: any }
|
||||
) {
|
||||
// tslint:disable-next-line:variable-name
|
||||
let _from;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { WebDriver, WebElement } from 'selenium-webdriver';
|
||||
import { WebDriver, WebElement, By } from 'selenium-webdriver';
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
import { WebElementWrapper } from './lib/web_element_wrapper';
|
||||
|
||||
|
@ -28,7 +28,6 @@ export async function FindProvider({ getService }: FtrProviderContext) {
|
|||
const retry = getService('retry');
|
||||
|
||||
const driver = webdriver.driver;
|
||||
const By = webdriver.By;
|
||||
const until = webdriver.until;
|
||||
const browserType = webdriver.browserType;
|
||||
|
||||
|
@ -36,9 +35,10 @@ export async function FindProvider({ getService }: FtrProviderContext) {
|
|||
const defaultFindTimeout = config.get('timeouts.find');
|
||||
const fixedHeaderHeight = config.get('layout.fixedHeaderHeight');
|
||||
|
||||
const wrap = (webElement: WebElement | WebElementWrapper) =>
|
||||
new WebElementWrapper(
|
||||
const wrap = (webElement: WebElement | WebElementWrapper, locator: By | null = null) =>
|
||||
WebElementWrapper.create(
|
||||
webElement,
|
||||
locator,
|
||||
webdriver,
|
||||
defaultFindTimeout,
|
||||
fixedHeaderHeight,
|
||||
|
@ -46,7 +46,13 @@ export async function FindProvider({ getService }: FtrProviderContext) {
|
|||
browserType
|
||||
);
|
||||
|
||||
const wrapAll = (webElements: Array<WebElement | WebElementWrapper>) => webElements.map(wrap);
|
||||
const wrapAll = (webElements: Array<WebElement | WebElementWrapper>) =>
|
||||
webElements.map(e => wrap(e));
|
||||
|
||||
const findAndWrap = async (locator: By, timeout: number): Promise<WebElementWrapper> => {
|
||||
const webElement = await driver.wait(until.elementLocated(locator), timeout);
|
||||
return wrap(webElement, locator);
|
||||
};
|
||||
|
||||
class Find {
|
||||
public currentWait = defaultFindTimeout;
|
||||
|
@ -56,7 +62,7 @@ export async function FindProvider({ getService }: FtrProviderContext) {
|
|||
timeout: number = defaultFindTimeout
|
||||
): Promise<WebElementWrapper> {
|
||||
log.debug(`Find.byName('${selector}') with timeout=${timeout}`);
|
||||
return wrap(await driver.wait(until.elementLocated(By.name(selector)), timeout));
|
||||
return await findAndWrap(By.name(selector), timeout);
|
||||
}
|
||||
|
||||
public async byCssSelector(
|
||||
|
@ -64,7 +70,7 @@ export async function FindProvider({ getService }: FtrProviderContext) {
|
|||
timeout: number = defaultFindTimeout
|
||||
): Promise<WebElementWrapper> {
|
||||
log.debug(`Find.findByCssSelector('${selector}') with timeout=${timeout}`);
|
||||
return wrap(await driver.wait(until.elementLocated(By.css(selector)), timeout));
|
||||
return findAndWrap(By.css(selector), timeout);
|
||||
}
|
||||
|
||||
public async byXPath(
|
||||
|
@ -72,7 +78,7 @@ export async function FindProvider({ getService }: FtrProviderContext) {
|
|||
timeout: number = defaultFindTimeout
|
||||
): Promise<WebElementWrapper> {
|
||||
log.debug(`Find.byXPath('${selector}') with timeout=${timeout}`);
|
||||
return wrap(await driver.wait(until.elementLocated(By.xpath(selector)), timeout));
|
||||
return findAndWrap(By.xpath(selector), timeout);
|
||||
}
|
||||
|
||||
public async byClassName(
|
||||
|
@ -80,7 +86,7 @@ export async function FindProvider({ getService }: FtrProviderContext) {
|
|||
timeout: number = defaultFindTimeout
|
||||
): Promise<WebElementWrapper> {
|
||||
log.debug(`Find.findByClassName('${selector}') with timeout=${timeout}`);
|
||||
return wrap(await driver.wait(until.elementLocated(By.className(selector)), timeout));
|
||||
return findAndWrap(By.className(selector), timeout);
|
||||
}
|
||||
|
||||
public async activeElement(): Promise<WebElementWrapper> {
|
||||
|
@ -107,7 +113,7 @@ export async function FindProvider({ getService }: FtrProviderContext) {
|
|||
});
|
||||
}
|
||||
|
||||
public async filterElementIsDisplayed(elements: any[]) {
|
||||
public async filterElementIsDisplayed(elements: WebElementWrapper[]) {
|
||||
if (elements.length === 0) {
|
||||
return [];
|
||||
} else {
|
||||
|
@ -178,7 +184,7 @@ export async function FindProvider({ getService }: FtrProviderContext) {
|
|||
): Promise<WebElementWrapper | never> {
|
||||
log.debug(`Find.descendantDisplayedByCssSelector('${selector}')`);
|
||||
const element = await parentElement._webElement.findElement(By.css(selector));
|
||||
const descendant = wrap(element);
|
||||
const descendant = wrap(element, By.css(selector));
|
||||
const isDisplayed = await descendant.isDisplayed();
|
||||
if (isDisplayed) {
|
||||
return descendant;
|
||||
|
@ -206,7 +212,7 @@ export async function FindProvider({ getService }: FtrProviderContext) {
|
|||
const element = await this.byLinkText(linkText, timeout);
|
||||
log.debug(`Wait for element become visible: ${linkText} with timeout=${timeout}`);
|
||||
await driver.wait(until.elementIsVisible(element._webElement), timeout);
|
||||
return wrap(element);
|
||||
return wrap(element, By.linkText(linkText));
|
||||
}
|
||||
|
||||
public async displayedByCssSelector(
|
||||
|
@ -217,7 +223,7 @@ export async function FindProvider({ getService }: FtrProviderContext) {
|
|||
const element = await this.byCssSelector(selector, timeout);
|
||||
log.debug(`Wait for element become visible: ${selector} with timeout=${timeout}`);
|
||||
await driver.wait(until.elementIsVisible(element._webElement), timeout);
|
||||
return wrap(element);
|
||||
return wrap(element, By.css(selector));
|
||||
}
|
||||
|
||||
public async byLinkText(
|
||||
|
@ -225,7 +231,7 @@ export async function FindProvider({ getService }: FtrProviderContext) {
|
|||
timeout: number = defaultFindTimeout
|
||||
): Promise<WebElementWrapper> {
|
||||
log.debug(`Find.byLinkText('${selector}') with timeout=${timeout}`);
|
||||
return wrap(await driver.wait(until.elementLocated(By.linkText(selector)), timeout));
|
||||
return findAndWrap(By.linkText(selector), timeout);
|
||||
}
|
||||
|
||||
public async byPartialLinkText(
|
||||
|
@ -233,9 +239,7 @@ export async function FindProvider({ getService }: FtrProviderContext) {
|
|||
timeout: number = defaultFindTimeout
|
||||
): Promise<WebElementWrapper> {
|
||||
log.debug(`Find.byPartialLinkText('${partialLinkText}') with timeout=${timeout}`);
|
||||
return wrap(
|
||||
await driver.wait(until.elementLocated(By.partialLinkText(partialLinkText)), timeout)
|
||||
);
|
||||
return findAndWrap(By.partialLinkText(partialLinkText), timeout);
|
||||
}
|
||||
|
||||
public async exists(
|
||||
|
@ -342,8 +346,7 @@ export async function FindProvider({ getService }: FtrProviderContext) {
|
|||
log.debug(`Find.byButtonText('${buttonText}') with timeout=${timeout}`);
|
||||
return await retry.tryForTime(timeout, async () => {
|
||||
// tslint:disable-next-line:variable-name
|
||||
const _element =
|
||||
element instanceof WebElementWrapper ? (element as any)._webElement : element;
|
||||
const _element = element instanceof WebElementWrapper ? element._webElement : element;
|
||||
const allButtons = wrapAll(await _element.findElements(By.tagName('button')));
|
||||
const buttonTexts = await Promise.all(
|
||||
allButtons.map(async el => {
|
||||
|
|
|
@ -41,25 +41,52 @@ interface TypeOptions {
|
|||
charByChar: boolean;
|
||||
}
|
||||
|
||||
const RETRY_CLICK_MAX_ATTEMPTS = 3;
|
||||
const RETRY_CLICK_RETRY_ON_ERRORS = [
|
||||
'ElementClickInterceptedError',
|
||||
'ElementNotInteractableError',
|
||||
'StaleElementReferenceError',
|
||||
];
|
||||
|
||||
export class WebElementWrapper {
|
||||
private By: typeof By = this.webDriver.By;
|
||||
private Keys: IKey = this.webDriver.Key;
|
||||
private driver: WebDriver = this.webDriver.driver;
|
||||
public _webElement: WebElement = this.webElement as WebElement;
|
||||
public LegacyAction: any = this.webDriver.LegacyActionSequence;
|
||||
|
||||
public static create(
|
||||
webElement: WebElement | WebElementWrapper,
|
||||
locator: By | null,
|
||||
webDriver: Driver,
|
||||
timeout: number,
|
||||
fixedHeaderHeight: number,
|
||||
logger: ToolingLog,
|
||||
browserType: string
|
||||
): WebElementWrapper {
|
||||
if (webElement instanceof WebElementWrapper) {
|
||||
return webElement;
|
||||
}
|
||||
|
||||
return new WebElementWrapper(
|
||||
webElement,
|
||||
locator,
|
||||
webDriver,
|
||||
timeout,
|
||||
fixedHeaderHeight,
|
||||
logger,
|
||||
browserType
|
||||
);
|
||||
}
|
||||
|
||||
constructor(
|
||||
private webElement: WebElementWrapper | WebElement,
|
||||
public _webElement: WebElement,
|
||||
private locator: By | null,
|
||||
private webDriver: Driver,
|
||||
private timeout: number,
|
||||
private fixedHeaderHeight: number,
|
||||
private logger: ToolingLog,
|
||||
private browserType: string
|
||||
) {
|
||||
if (webElement instanceof WebElementWrapper) {
|
||||
return webElement;
|
||||
}
|
||||
}
|
||||
) {}
|
||||
|
||||
private async _findWithCustomTimeout(
|
||||
findFunction: () => Promise<Array<WebElement | WebElementWrapper>>,
|
||||
|
@ -75,9 +102,10 @@ export class WebElementWrapper {
|
|||
return elements;
|
||||
}
|
||||
|
||||
private _wrap(otherWebElement: WebElement | WebElementWrapper) {
|
||||
return new WebElementWrapper(
|
||||
private _wrap(otherWebElement: WebElement | WebElementWrapper, locator: By | null = null) {
|
||||
return WebElementWrapper.create(
|
||||
otherWebElement,
|
||||
locator,
|
||||
this.webDriver,
|
||||
this.timeout,
|
||||
this.fixedHeaderHeight,
|
||||
|
@ -90,6 +118,32 @@ export class WebElementWrapper {
|
|||
return otherWebElements.map(e => this._wrap(e));
|
||||
}
|
||||
|
||||
private async retryCall<T>(
|
||||
fn: (wrapper: this) => T | Promise<T>,
|
||||
attemptsRemaining: number = RETRY_CLICK_MAX_ATTEMPTS
|
||||
): Promise<T> {
|
||||
try {
|
||||
return await fn(this);
|
||||
} catch (err) {
|
||||
if (
|
||||
!RETRY_CLICK_RETRY_ON_ERRORS.includes(err.name) ||
|
||||
this.locator === null ||
|
||||
attemptsRemaining === 0
|
||||
) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
this.logger.warning(`WebElementWrapper.${fn.name}: ${err.message}`);
|
||||
this.logger.debug(
|
||||
`finding element '${this.locator.toString()}' again, ${attemptsRemaining - 1} attempts left`
|
||||
);
|
||||
|
||||
await delay(200);
|
||||
this._webElement = await this.driver.findElement(this.locator);
|
||||
return await this.retryCall(fn, attemptsRemaining - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the element would be visible to an actual user. This means
|
||||
* that the following types of elements are considered to be not displayed:
|
||||
|
@ -104,8 +158,10 @@ export class WebElementWrapper {
|
|||
*
|
||||
* @return {Promise<boolean>}
|
||||
*/
|
||||
public async isDisplayed(): Promise<boolean> {
|
||||
return await this._webElement.isDisplayed();
|
||||
public async isDisplayed() {
|
||||
return await this.retryCall(async function isDisplayed(wrapper) {
|
||||
return await wrapper._webElement.isDisplayed();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,8 +170,10 @@ export class WebElementWrapper {
|
|||
*
|
||||
* @return {Promise<boolean>}
|
||||
*/
|
||||
public async isEnabled(): Promise<boolean> {
|
||||
return await this._webElement.isEnabled();
|
||||
public async isEnabled() {
|
||||
return await this.retryCall(async function isEnabled(wrapper) {
|
||||
return await wrapper._webElement.isEnabled();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,8 +182,10 @@ export class WebElementWrapper {
|
|||
*
|
||||
* @return {Promise<boolean>}
|
||||
*/
|
||||
public async isSelected(): Promise<boolean> {
|
||||
return await this._webElement.isSelected();
|
||||
public async isSelected() {
|
||||
return await this.retryCall(async function isSelected(wrapper) {
|
||||
return await wrapper._webElement.isSelected();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -134,9 +194,11 @@ export class WebElementWrapper {
|
|||
*
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
public async click(): Promise<void> {
|
||||
await this.scrollIntoViewIfNecessary();
|
||||
await this._webElement.click();
|
||||
public async click() {
|
||||
await this.retryCall(async function click(wrapper) {
|
||||
await wrapper.scrollIntoViewIfNecessary();
|
||||
await wrapper._webElement.click();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,8 +210,10 @@ export class WebElementWrapper {
|
|||
*/
|
||||
async clearValue() {
|
||||
// https://bugs.chromium.org/p/chromedriver/issues/detail?id=2702
|
||||
// await this._webElement.clear();
|
||||
await this.driver.executeScript(`arguments[0].value=''`, this._webElement);
|
||||
// await wrapper.webElement.clear();
|
||||
await this.retryCall(async function clearValue(wrapper) {
|
||||
await wrapper.driver.executeScript(`arguments[0].value=''`, wrapper._webElement);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -157,7 +221,7 @@ export class WebElementWrapper {
|
|||
* @param {{ charByChar: boolean }} options
|
||||
* @default { charByChar: false }
|
||||
*/
|
||||
async clearValueWithKeyboard(options: TypeOptions = { charByChar: false }): Promise<void> {
|
||||
async clearValueWithKeyboard(options: TypeOptions = { charByChar: false }) {
|
||||
if (options.charByChar === true) {
|
||||
const value = await this.getAttribute('value');
|
||||
for (let i = 1; i <= value.length; i++) {
|
||||
|
@ -167,7 +231,9 @@ export class WebElementWrapper {
|
|||
} else {
|
||||
if (this.browserType === Browsers.Chrome) {
|
||||
// https://bugs.chromium.org/p/chromedriver/issues/detail?id=30
|
||||
await this.driver.executeScript(`arguments[0].select();`, this._webElement);
|
||||
await this.retryCall(async function clearValueWithKeyboard(wrapper) {
|
||||
await wrapper.driver.executeScript(`arguments[0].select();`, wrapper._webElement);
|
||||
});
|
||||
await this.pressKeys(this.Keys.BACK_SPACE);
|
||||
} else {
|
||||
const selectionKey = this.Keys[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'];
|
||||
|
@ -194,17 +260,18 @@ export class WebElementWrapper {
|
|||
* @param {charByChar: boolean} options
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
public async type(
|
||||
value: string | string[],
|
||||
options: TypeOptions = { charByChar: false }
|
||||
): Promise<void> {
|
||||
public async type(value: string | string[], options: TypeOptions = { charByChar: false }) {
|
||||
if (options.charByChar) {
|
||||
for (const char of value) {
|
||||
await this._webElement.sendKeys(char);
|
||||
await delay(100);
|
||||
await this.retryCall(async function type(wrapper) {
|
||||
await wrapper._webElement.sendKeys(char);
|
||||
await delay(100);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
await this._webElement.sendKeys(...value);
|
||||
await this.retryCall(async function type(wrapper) {
|
||||
await wrapper._webElement.sendKeys(...value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,12 +285,14 @@ export class WebElementWrapper {
|
|||
public async pressKeys<T extends IKey>(keys: T | T[]): Promise<void>;
|
||||
public async pressKeys<T extends string>(keys: T | T[]): Promise<void>;
|
||||
public async pressKeys(keys: string): Promise<void> {
|
||||
if (Array.isArray(keys)) {
|
||||
const chord = this.Keys.chord(keys);
|
||||
await this._webElement.sendKeys(chord);
|
||||
} else {
|
||||
await this._webElement.sendKeys(keys);
|
||||
}
|
||||
await this.retryCall(async function pressKeys(wrapper) {
|
||||
if (Array.isArray(keys)) {
|
||||
const chord = wrapper.Keys.chord(keys);
|
||||
await wrapper._webElement.sendKeys(chord);
|
||||
} else {
|
||||
await wrapper._webElement.sendKeys(keys);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -237,8 +306,10 @@ export class WebElementWrapper {
|
|||
*
|
||||
* @param {string} name
|
||||
*/
|
||||
public async getAttribute(name: string): Promise<string> {
|
||||
return await this._webElement.getAttribute(name);
|
||||
public async getAttribute(name: string) {
|
||||
return await this.retryCall(async function getAttribute(wrapper) {
|
||||
return await wrapper._webElement.getAttribute(name);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -276,8 +347,10 @@ export class WebElementWrapper {
|
|||
* @param {string} propertyName
|
||||
* @return {Promise<string>}
|
||||
*/
|
||||
public async getComputedStyle(propertyName: string): Promise<string> {
|
||||
return await this._webElement.getCssValue(propertyName);
|
||||
public async getComputedStyle(propertyName: string) {
|
||||
return await this.retryCall(async function getComputedStyle(wrapper) {
|
||||
return await wrapper._webElement.getCssValue(propertyName);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -287,8 +360,10 @@ export class WebElementWrapper {
|
|||
*
|
||||
* @return {Promise<string>}
|
||||
*/
|
||||
public async getVisibleText(): Promise<string> {
|
||||
return await this._webElement.getText();
|
||||
public async getVisibleText() {
|
||||
return await this.retryCall(async function getVisibleText(wrapper) {
|
||||
return await wrapper._webElement.getText();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -300,7 +375,9 @@ export class WebElementWrapper {
|
|||
public async getTagName<T extends keyof HTMLElementTagNameMap>(): Promise<T>;
|
||||
public async getTagName<T extends string>(): Promise<T>;
|
||||
public async getTagName(): Promise<string> {
|
||||
return await this._webElement.getTagName();
|
||||
return await this.retryCall(async function getTagName(wrapper) {
|
||||
return await wrapper._webElement.getTagName();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -311,7 +388,9 @@ export class WebElementWrapper {
|
|||
* @return {Promise<{height: number, width: number, x: number, y: number}>}
|
||||
*/
|
||||
public async getPosition(): Promise<{ height: number; width: number; x: number; y: number }> {
|
||||
return await (this._webElement as any).getRect();
|
||||
return await this.retryCall(async function getPosition(wrapper) {
|
||||
return await (wrapper._webElement as any).getRect();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -322,7 +401,9 @@ export class WebElementWrapper {
|
|||
* @return {Promise<{height: number, width: number, x: number, y: number}>}
|
||||
*/
|
||||
public async getSize(): Promise<{ height: number; width: number; x: number; y: number }> {
|
||||
return await (this._webElement as any).getRect();
|
||||
return await this.retryCall(async function getSize(wrapper) {
|
||||
return await (wrapper._webElement as any).getRect();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -331,20 +412,22 @@ export class WebElementWrapper {
|
|||
*
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
public async moveMouseTo(): Promise<void> {
|
||||
await this.scrollIntoViewIfNecessary();
|
||||
if (this.browserType === Browsers.Firefox) {
|
||||
const actions = (this.driver as any).actions();
|
||||
await actions.move({ x: 0, y: 0 }).perform();
|
||||
await actions.move({ x: 10, y: 10, origin: this._webElement }).perform();
|
||||
} else {
|
||||
const mouse = (this.driver.actions() as any).mouse();
|
||||
const actions = (this.driver as any).actions({ bridge: true });
|
||||
await actions
|
||||
.pause(mouse)
|
||||
.move({ origin: this._webElement })
|
||||
.perform();
|
||||
}
|
||||
public async moveMouseTo() {
|
||||
await this.retryCall(async function moveMouseTo(wrapper) {
|
||||
await wrapper.scrollIntoViewIfNecessary();
|
||||
if (wrapper.browserType === Browsers.Firefox) {
|
||||
const actions = (wrapper.driver as any).actions();
|
||||
await actions.move({ x: 0, y: 0 }).perform();
|
||||
await actions.move({ x: 10, y: 10, origin: wrapper._webElement }).perform();
|
||||
} else {
|
||||
const mouse = (wrapper.driver.actions() as any).mouse();
|
||||
const actions = (wrapper.driver as any).actions({ bridge: true });
|
||||
await actions
|
||||
.pause(mouse)
|
||||
.move({ origin: wrapper._webElement })
|
||||
.perform();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -354,8 +437,13 @@ export class WebElementWrapper {
|
|||
* @param {string} selector
|
||||
* @return {Promise<WebElementWrapper>}
|
||||
*/
|
||||
public async findByCssSelector(selector: string): Promise<WebElementWrapper> {
|
||||
return this._wrap(await this._webElement.findElement(this.By.css(selector)));
|
||||
public async findByCssSelector(selector: string) {
|
||||
return await this.retryCall(async function findByCssSelector(wrapper) {
|
||||
return wrapper._wrap(
|
||||
await wrapper._webElement.findElement(wrapper.By.css(selector)),
|
||||
wrapper.By.css(selector)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -367,12 +455,14 @@ export class WebElementWrapper {
|
|||
* @return {Promise<WebElementWrapper[]>}
|
||||
*/
|
||||
public async findAllByCssSelector(selector: string, timeout?: number) {
|
||||
return this._wrapAll(
|
||||
await this._findWithCustomTimeout(
|
||||
async () => await this._webElement.findElements(this.By.css(selector)),
|
||||
timeout
|
||||
)
|
||||
);
|
||||
return await this.retryCall(async function findAllByCssSelector(wrapper) {
|
||||
return wrapper._wrapAll(
|
||||
await wrapper._findWithCustomTimeout(
|
||||
async () => await wrapper._webElement.findElements(wrapper.By.css(selector)),
|
||||
timeout
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -382,8 +472,13 @@ export class WebElementWrapper {
|
|||
* @param {string} className
|
||||
* @return {Promise<WebElementWrapper>}
|
||||
*/
|
||||
public async findByClassName(className: string): Promise<WebElementWrapper> {
|
||||
return this._wrap(await this._webElement.findElement(this.By.className(className)));
|
||||
public async findByClassName(className: string) {
|
||||
return await this.retryCall(async function findByClassName(wrapper) {
|
||||
return wrapper._wrap(
|
||||
await wrapper._webElement.findElement(wrapper.By.className(className)),
|
||||
wrapper.By.className(className)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -394,16 +489,15 @@ export class WebElementWrapper {
|
|||
* @param {number} timeout
|
||||
* @return {Promise<WebElementWrapper[]>}
|
||||
*/
|
||||
public async findAllByClassName(
|
||||
className: string,
|
||||
timeout?: number
|
||||
): Promise<WebElementWrapper[]> {
|
||||
return this._wrapAll(
|
||||
await this._findWithCustomTimeout(
|
||||
async () => await this._webElement.findElements(this.By.className(className)),
|
||||
timeout
|
||||
)
|
||||
);
|
||||
public async findAllByClassName(className: string, timeout?: number) {
|
||||
return await this.retryCall(async function findAllByClassName(wrapper) {
|
||||
return wrapper._wrapAll(
|
||||
await wrapper._findWithCustomTimeout(
|
||||
async () => await wrapper._webElement.findElements(wrapper.By.className(className)),
|
||||
timeout
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -418,7 +512,12 @@ export class WebElementWrapper {
|
|||
): Promise<WebElementWrapper>;
|
||||
public async findByTagName<T extends string>(tagName: T): Promise<WebElementWrapper>;
|
||||
public async findByTagName(tagName: string): Promise<WebElementWrapper> {
|
||||
return this._wrap(await this._webElement.findElement(this.By.tagName(tagName)));
|
||||
return await this.retryCall(async function findByTagName(wrapper) {
|
||||
return wrapper._wrap(
|
||||
await wrapper._webElement.findElement(wrapper.By.tagName(tagName)),
|
||||
wrapper.By.tagName(tagName)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -438,12 +537,14 @@ export class WebElementWrapper {
|
|||
timeout?: number
|
||||
): Promise<WebElementWrapper[]>;
|
||||
public async findAllByTagName(tagName: string, timeout?: number): Promise<WebElementWrapper[]> {
|
||||
return this._wrapAll(
|
||||
await this._findWithCustomTimeout(
|
||||
async () => await this._webElement.findElements(this.By.tagName(tagName)),
|
||||
timeout
|
||||
)
|
||||
);
|
||||
return await this.retryCall(async function findAllByTagName(wrapper) {
|
||||
return wrapper._wrapAll(
|
||||
await wrapper._findWithCustomTimeout(
|
||||
async () => await wrapper._webElement.findElements(wrapper.By.tagName(tagName)),
|
||||
timeout
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -453,8 +554,13 @@ export class WebElementWrapper {
|
|||
* @param {string} selector
|
||||
* @return {Promise<WebElementWrapper>}
|
||||
*/
|
||||
async findByXpath(selector: string): Promise<WebElementWrapper> {
|
||||
return this._wrap(await this._webElement.findElement(this.By.xpath(selector)));
|
||||
async findByXpath(selector: string) {
|
||||
return await this.retryCall(async function findByXpath(wrapper) {
|
||||
return wrapper._wrap(
|
||||
await wrapper._webElement.findElement(wrapper.By.xpath(selector)),
|
||||
wrapper.By.xpath(selector)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -465,41 +571,52 @@ export class WebElementWrapper {
|
|||
* @param {number} timeout
|
||||
* @return {Promise<WebElementWrapper[]>}
|
||||
*/
|
||||
public async findAllByXpath(selector: string, timeout?: number): Promise<WebElementWrapper[]> {
|
||||
return this._wrapAll(
|
||||
await this._findWithCustomTimeout(
|
||||
async () => await this._webElement.findElements(this.By.xpath(selector)),
|
||||
timeout
|
||||
)
|
||||
);
|
||||
public async findAllByXpath(selector: string, timeout?: number) {
|
||||
return await this.retryCall(async function findAllByXpath(wrapper) {
|
||||
return wrapper._wrapAll(
|
||||
await wrapper._findWithCustomTimeout(
|
||||
async () => await wrapper._webElement.findElements(wrapper.By.xpath(selector)),
|
||||
timeout
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first element inside this element matching the given partial link text.
|
||||
* https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#findElement
|
||||
*
|
||||
* @param {string} selector
|
||||
* @param {string} linkText
|
||||
* @return {Promise<WebElementWrapper[]>}
|
||||
*/
|
||||
public async findByPartialLinkText(linkText: string): Promise<WebElementWrapper> {
|
||||
return await this._wrap(await this._webElement.findElement(this.By.partialLinkText(linkText)));
|
||||
public async findByPartialLinkText(linkText: string) {
|
||||
return await this.retryCall(async function findByPartialLinkText(wrapper) {
|
||||
return wrapper._wrap(
|
||||
await wrapper._webElement.findElement(wrapper.By.partialLinkText(linkText)),
|
||||
wrapper.By.partialLinkText(linkText)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all elements inside this element matching the given partial link text.
|
||||
* https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#findElement
|
||||
*
|
||||
* @param {string} selector
|
||||
* @param {string} linkText
|
||||
* @param {number} timeout
|
||||
* @return {Promise<WebElementWrapper[]>}
|
||||
*/
|
||||
public async findAllByPartialLinkText(linkText: string, timeout?: number) {
|
||||
return this._wrapAll(
|
||||
await this._findWithCustomTimeout(
|
||||
async () => await this._webElement.findElements(this.By.partialLinkText(linkText)),
|
||||
timeout
|
||||
)
|
||||
);
|
||||
return await this.retryCall(async function findAllByPartialLinkText(
|
||||
wrapper: WebElementWrapper
|
||||
) {
|
||||
return wrapper._wrapAll(
|
||||
await wrapper._findWithCustomTimeout(
|
||||
async () => await wrapper._webElement.findElements(wrapper.By.partialLinkText(linkText)),
|
||||
timeout
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue