browsertime
Version:
Get performance metrics from your web page using Browsertime.
244 lines (234 loc) • 7.36 kB
JavaScript
import webdriver, { By } from 'selenium-webdriver';
import { getLogger } from '@sitespeed.io/log';
import { executeCommand } from './commandHelper.js';
import { parseSelector } from './selectorParser.js';
const log = getLogger('browsertime.command.addText');
/**
* Provides functionality to add text to elements on a web page using various selectors.
* @class
* @hideconstructor
*/
export class AddText {
constructor(browser, options) {
/**
* @private
*/
this.browser = browser;
/**
* @private
*/
this.options = options;
}
/**
* @private
*/
async _waitForElement(driver, locator) {
const timeout = this.options?.timeouts?.elementWait ?? 0;
if (timeout > 0) {
await driver.wait(webdriver.until.elementLocated(locator), timeout);
}
}
/**
* @private
*/
async _getUrl() {
try {
return ` on ${await this.browser.getDriver().getCurrentUrl()}`;
} catch {
return '';
}
}
/**
* Adds text to an element using a unified selector string.
* Supports CSS selectors (default), and prefix-based strategies:
* 'id:myId', 'xpath://input', 'name:email', 'class:input-field'.
*
* @async
* @param {string} selector - The selector string. CSS by default, or use a prefix.
* @param {string} text - The text string to add.
* @returns {Promise<void>} A promise that resolves when the text has been added.
* @throws {Error} Throws an error if the element is not found.
*/
async run(selector, text) {
const { locator, description } = parseSelector(selector);
return executeCommand(
log,
'Could not add text %s to %s',
description,
async () => {
const driver = this.browser.getDriver();
await this._waitForElement(driver, locator);
const element = await driver.findElement(locator);
await element.clear();
return element.sendKeys(text);
},
this.browser
);
}
/**
* Adds text to an element identified by its ID.
*
* @async
* @private
* @example commands.addText.byId('mytext', 'id');
* @param {string} text - The text string to add.
* @param {string} id - The ID of the element.
* @returns {Promise<void>} A promise that resolves when the text has been added.
* @throws {Error} Throws an error if the element is not found.
*/
async byId(text, id) {
const driver = this.browser.getDriver();
try {
const locator = By.id(id);
await this._waitForElement(driver, locator);
const element = await driver.findElement(locator);
// make sure we clear it
await element.clear();
return element.sendKeys(text);
} catch (error) {
const url = await this._getUrl();
log.error(
'Could not add text %s to id %s error:%s',
text,
id,
error.message
);
log.verbose(error);
throw new Error(`Could not add text ${text} to id ${id}${url}`);
}
}
/**
* Adds text to an element identified by its XPath.
*
* @async
* @private
* @example commands.addText.byXpath('mytext', 'xpath');
* @param {string} text - The text string to add.
* @param {string} xpath - The XPath of the element.
* @returns {Promise<void>} A promise that resolves when the text has been added.
* @throws {Error} Throws an error if the element is not found.
*/
async byXpath(text, xpath) {
const driver = this.browser.getDriver();
try {
const locator = By.xpath(xpath);
await this._waitForElement(driver, locator);
const element = await driver.findElement(locator);
// make sure we clear it
await element.clear();
return element.sendKeys(text);
} catch (error) {
const url = await this._getUrl();
log.error(
'Could not add text %s to xpath %s error: %s',
text,
xpath,
error.message
);
log.verbose(error);
throw new Error(`Could not add text ${text} to xpath ${xpath}${url}`);
}
}
/**
* Adds text to an element identified by its CSS selector.
*
* @async
* @private
* @example commands.addText.bySelector('mytext', 'selector');
* @param {string} text - The text string to add.
* @param {string} selector - The CSS selector of the element.
* @returns {Promise<void>} A promise that resolves when the text has been added.
* @throws {Error} Throws an error if the element is not found.
*/
async bySelector(text, selector) {
const driver = this.browser.getDriver();
try {
const locator = By.css(selector);
await this._waitForElement(driver, locator);
const element = await driver.findElement(locator);
// make sure we clear it
await element.clear();
return element.sendKeys(text);
} catch (error) {
const url = await this._getUrl();
log.error(
'Could not add text %s to selector %s error: %s',
text,
selector,
error.message
);
log.verbose(error);
throw new Error(
`Could not add text ${text} to selector ${selector}${url}`
);
}
}
/**
* Adds text to an element identified by its class name.
*
* @async
* @private
* @example commands.addText.byClassName('mytext', 'className');
* @param {string} text - The text string to add.
* @param {string} className - The class name of the element.
* @returns {Promise<void>} A promise that resolves when the text has been added.
* @throws {Error} Throws an error if the element is not found.
*/
async byClassName(text, className) {
const driver = this.browser.getDriver();
try {
const locator = By.className(className);
await this._waitForElement(driver, locator);
const element = await driver.findElement(locator);
// make sure we clear it
await element.clear();
return element.sendKeys(text);
} catch (error) {
const url = await this._getUrl();
log.error(
'Could not add text %s to class name %s error: %s',
text,
className,
error.message
);
log.verbose(error);
throw new Error(
`Could not add text ${text} to class name ${className}${url}`
);
}
}
/**
* Adds text to an element identified by its name attribute.
*
* @async
* @private
* @example commands.addText.byName('mytext', 'name');
* @param {string} text - The text string to add.
* @param {string} name - The name attribute of the element.
* @returns {Promise<void>} A promise that resolves when the text has been added.
* @throws {Error} Throws an error if the element is not found.
*/
async byName(text, name) {
const driver = this.browser.getDriver();
try {
const locator = By.name(name);
await this._waitForElement(driver, locator);
const element = await driver.findElement(locator);
// make sure we clear it
await element.clear();
return element.sendKeys(text);
} catch (error) {
const url = await this._getUrl();
log.error(
'Could not add text %s to name attribute %s error: %s',
text,
name,
error.message
);
log.verbose(error);
throw new Error(
`Could not add text ${text} to name attribute ${name}${url}`
);
}
}
}