The Search/getElementAttributeValue extension locates an element on the current web page using XPath, CSS selector, ID, or a selector object, then returns the requested attribute or DOM property value from the matched element.
This is useful when a journey needs to capture values such as class, title, href, value, or another element attribute for validation, reporting, or downstream test logic.
Parameters:
-
elementrequired, a selector string or JSON string/object containing aselectorsarray. A string starting with/is treated as XPath; other strings are treated as CSS selectors. Selector objects supportXPATH,CSS_SELECTOR, andIDtypes; -
attributerequired, a string containing the attribute or DOM property name to read from the located element.
Note: The extension first attempts to parse element as JSON. If parsing fails, it treats the value as a direct selector string. It waits for the element by retrying up to 1000 times with a 50 ms interval before failing.
NLP usage
Use the extension in a journey by calling Search/getElementAttributeValue with the execute command. Pass each value to the matching extension input using as element and as attribute.
Note: The user-provided configuration for this article is Run asynchronously: No. The source code still uses Promise-based waiting internally, so confirm this setting in your Virtuoso instance if the journey needs to wait for delayed elements.
execute "Search/getElementAttributeValue" using "//a[text()='Try it Yourself »']" as element using "class" as attribute returning $classValueexecute "Search/getElementAttributeValue" using "//a[text()='Log in to track progress']" as element using "title" as attribute returning $titleValueYou can also pass the selector and attribute from variables when the target element or attribute name changes during the journey.
execute "Search/getElementAttributeValue" using "$elementSelector" as element using "$attributeName" as attribute returning $attributeValuestore value "//a[text()='Try it Yourself »']" in $elementSelector
store value "class" in $attributeName
execute "Search/getElementAttributeValue" using "$elementSelector" as element using "$attributeName" as attribute returning $attributeValueExample output when the requested attribute exists:
w3-btn w3-margin-bottomThis extension does not require any external resource.
The extension should be configured as:
- Run asynchronously: No
- Scope: Global
Limitation: This extension only works against elements available in the current page DOM and supports only XPath, CSS selector, and ID selector types. It returns the first matching element only, does not search inside inaccessible iframes or closed shadow DOM, and may return undefined or null when the requested attribute/property does not exist. Although this article is configured with Run asynchronously: No as requested, the source uses async, await, and Promise-based retry logic internally, so timing behavior should be validated in the target journey.
Add the extension to your Virtuoso instance
Select the domain that matches your Virtuoso account.
View source
Last updated: 25/05/2026
Resources:
This extension does not require any external resource.
// Note this extension is not a product feature of Virtuoso and is not officially supported
// Extensions use javascript which may or may not be compatible with systems under test (SUTs)
// We welcome you to use this extension or adapt it for your needs
if (!element) throw new Error('No element was supplied');
function getElementByXpath(path) {
const result = document.evaluate(path, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
return result.snapshotLength > 0 ? result.snapshotItem(0) : null;
}
function findElement(element) {
try {
element = JSON.parse(element);
} catch (e) { }
const selectors = (typeof element === 'string') ? [{ type: element.startsWith('/') ? 'XPATH' : 'CSS_SELECTOR', value: element }] : element.selectors;
for (let i in selectors) {
const selector = selectors[i];
if (!selector.type) continue;
let el = null;
switch (selector.type) {
case 'XPATH':
el = getElementByXpath(selector.value);
break;
case 'CSS_SELECTOR':
el = document.querySelector(selector.value);
break;
case 'ID':
el = document.getElementById(selector.value);
break;
default:
throw new Error(`Unsupported selector type: ${selector.type}`);
}
if (el) return el;
}
return null;
}
async function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const MAX_RETRIES = 1000;
const SLEEP_INTERVAL = 50; // ms
async function waitForElement(element) {
let retries = 0;
while (retries < MAX_RETRIES) {
const el = findElement(element);
if (el) return el;
retries++;
await sleep(SLEEP_INTERVAL);
}
return null;
}
async function getElementAttributeValue(element, attribute) {
const el = await waitForElement(element);
if (!el) throw new Error('Element was not found');
const attr = el[attribute] || el.getAttribute(attribute);
return attr;
}
return getElementAttributeValue(element, attribute);
Comments
0 comments
Please sign in to leave a comment.