Getting text from a node - selenium

I have a piece of HTML like this:
<a href="/something">
Title
<span>Author</span>
</a>
I got a WebElement that matches this HTML. How can I extract only "Title" from it? Method .getText() returns "Title\nAuthor"...

You can't do this in the WebDriver API, you have to do it in your code. For example:
var textOfA = theAElement.getText();
var textOfSpan = theSpanElement.getText();
var text = textOfA.substr(0, textOfA.length - textOfSpan.length).trim('\n');
Note that the trailing newline is actually part of the text of the <a> element, so if you don't want it, you need to strip it.

Here is the method developed in python.
def get_text_exclude_children(element):
return driver.execute_script(
"""
var parent = arguments[0];
var child = parent.firstChild;
var textValue = "";
while(child) {
if (child.nodeType === Node.TEXT_NODE)
textValue += child.textContent;
child = child.nextSibling;
}
return textValue;""",
element).strip()
How to use in this:
liElement = driver.find_element_by_xpath("//a[#href='your_href_goes_here']")
liOnlyText = get_text_exclude_children(liElement)
print(liOnlyText)
Please use your possible strategy to get the element, this method need an element from which you need the text (without children text).

If using Python:
[x['textContent'].strip() for x in element.get_property('childNodes') if isinstance(x, dict)]
Where element is your element.
This will return ['Title', ''] (because there are spaces after span).

you can use jsexecutor to iterate the child nodes, trap the textNode 'Title' and then return its content like below
WebElement link = driver.findElement(By.xpath("//a[#href='something']"));
JavascriptExecutor js = ((JavascriptExecutor)driver);
String authorText = (String) js.executeScript("for(var i = 0; i < arguments[0].childNodes.length; i++) {
if(arguments[0].childNodes[i].nodeName == \"#text\") { return arguments[0].childNodes[i].textContent; } }", link);
The javascript code block above iterates both textNode ('Title') and SPAN ('Author') but returns only the text content of textNode.
Note: Previous to this, I have tried including text node in xpath like below, but webdriver throws invalidselector exception as it requires element not textnode
WebElement link = driver.findElement(By.xpath("//a[#href='something']/text()"));

Verify the element present for "//a[normalize-space(text())=Title]". It will return true if the text present inside 'a' tag is 'Title'.

Related

Selenium - how to select each text object (one by one)

Im using selenium in Katalon.
I wonder how I can select two text object under "h3" tag.
And I want to select them one by one.
This is the html:
This is the code Im having right now
I have tried some options, and commented them out
And I have this loop cause I have some phone number blocks that I want to loop through.
Hope someone can help me :)
def phoneNumbersBlock = driver.findElements(By.xpath("//li[#class='ng-untouched ng-pristine ng-valid ng-star-inserted']"))
def phoneNumbersBlockCount = phoneNumbersBlock.size()
println("PhoneNumber count: "+phoneNumbersBlockCount)
for (int i = 0; i < phoneNumbersBlockCount; i++) {
//def phoneNumber = phoneNumbersBlock[i].findElement(By.tagName("h3")).getText();
//def phoneNumber = phoneNumbersBlock[i].findElement(By.xpath("//h3//text")).getText();
//def phoneNumber = driver.findElement(By.xpath("//li[#class='ng-untouched ng-pristine ng-valid ng-star-inserted']//h3/text()[1]"))
//def phoneNumber = phoneNumbersBlock[i].findElements(By.tagName("h3"))[0].getText();
def phoneNumber = phoneNumbersBlock[i].findElement(By.cssSelector("div > h3:nth-child(1)")).getText();
println("PhoneNumber "+i+": "+phoneNumber)
def phoneNumberText = phoneNumbersBlock[i].findElement(By.tagName("h3")).getText();
println("PhoneNumber Text "+i+": "+phoneNumberText)
}
The console output gives me this right now:
PhoneNumber count: 3
PhoneNumber 0: 070265895 (SLWEB AUTOTEST)
PhoneNumber Text 0: 070265895 (SLWEB AUTOTEST)
This is a text within a single node (element). Based on everything I know about elements location, there is no way to understand, is the text partiated, or it's a singe string.
I can suggest only trying to locate the parrent element and execute js
WebElement parent = driver.findElement(By.xpath("//h3/.."));
String innerHtml = ((JavaScriptExecutor)driver).executeScript("return arguments[0].innerHTML", parent);
The output will contain pure html, you'll need to split it on parts and extract the content using String methods.

Get error [object Text]. It should be an element

Trying to get the text from the div with xPath. Finds information in the browser good, but when i try to run with an idea than i get error:"is: [object Text]. It should be an element."
List<WebElement> priceGameWebElement = webDriver.findElements(By.xpath("//div[contains(#class,'search_price')]" +
"/text()[normalize-space()][1]"));
What do I need to do to make everything work?
You can "interrupt" your query before the /text()... part like this:
List<WebElement> priceGameWebElement = webDriver.findElements(By.xpath("//div[contains(#class,'search_price')]"));
Then you should get a List<WebElement> which contains the elements with the text() nodes for further distinction. They could probably be queried with the .getText() function.
If for some reason you cannot exclude text() from XPath and you need just extract the text of the element, then there is a workaround: use method document.evaluate() from JavaScript.
Code example:
String textObjectXpath = "\"//*[local-name() = 'text'][#x='8']/text()\"";
String script = "var element = document.evaluate("
+ textObjectXpath
+ ", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
+ "if (element) {return element.nodeValue;}";
String extractedText = (String) ((JavascriptExecutor)driver).executeScript(script);
The if statement "if (element) {return element.nodeValue;}" could be omitted if you don't care about the scenario when the element will be without text. In a such case, you may want to replace the line with "return element.nodeValue;"

Selenium WebDriver get text from input field

I'm writing a test to assert the default text value within an <input> tag. However, it's not playing ball:
Assert.assertThat(webDriver.findElement(By.id("inputTag")).getText(), Matchers.is("2"));
This is the input element - you need to get the value attribute:
webDriver.findElement(By.id("inputTag")).getAttribute("value")
The most reliable solution I found, is executing a JavaScript script and return the value attribute of the HTMLInputElement from JavaScript.
I have tested this in several ways and the value was always correct, even after changing the input field value.
PHP
$input = $driver->findElement( WebDriverBy::id( 'inputTag' ) );
$value = $driver->executeScript( 'return arguments[0].value', $input );
// A custom PHP function that returns the value of an input field:
function getValue(RemoteWebDriver $driver, WebDriverBy $by ) {
return $driver->executeScript(
'return arguments[0].value',
$driver->findElement( $by )
);
}
// Sample usage:
$value = getValue( $driver, WebDriverBy::id( 'inputTag' ) );
Java
//driver being your WebDriver
JavascriptExecutor js = (JavascriptExecutor) driver;
WebElement inpElement = driver.findElement(By.id("inputTag"));
String text = (String) js.executeScript("return arguments[0].value", inpElement);

Incrementing value with Selenium IDE

How do I increment value of img path when said path looks like this?
//ab[x]/img
X value increasing by 1 and has a limit of 50.
Trying to write a test case on how to click on several images on website.
Edit: Just wanted to add that I'm just starting with Selenium IDE and using standart commands.
Solution 1: Format your xpath path selector
for(int i=1; i<=numberOfImages; i++) {
String path = String.format("//ab[%d]/img", i);
WebElement image = driver.findElement(By.xpath(path));
if(image != null) {
image.click();
}
}
Solution 2: Select all elements that "//ab/img" returns and iterate over them.
String path = "//ab/img";
List<WebElement> imgElements = driver.findElements(By.xpath(path)); //notice the plural
for(WebElement image : imgElements) {
image.click();
}

How to get style sheet property value by webdriver?

I want to know whether content menu of drop down is displayed or none. I want to click on that menu if it's display none. and keep as it is if blocked. the property value is like this:
div id="section_content_23" class="thread-content" style="display: none;" i have xpath of title is like ex 'section_title_23'. i just want to know the style is "display: none;" or style = "display: blocked";
I have write code for this like:
else if (str.contains("section_title_"))
{
//String xpath;
String[] retval = str.split("_", 3);
String no = retval[2];
//
displaylinkhandler = QuickCap.driver.findElement(By.id("section_content_" + no)).getAttribute("style");
//displaylinkhandler = QuickCap.driver.findElement(By.id("section_content_" + no)).getAttribute("section_content_"+no);
//displaylinkhandler = QuickCap.driver.findElement(By.xpath(xpath)).getText();
//boolean show = displaylinkhandler.contains("display: none;");
if(displaylinkhandler == null){
QuickCap.driver.findElement(By.xpath(str)).click();
}
indexBoolean = TitleCheck.validate();
}
here str is xpath & displaylinkhandler is like string.
Thanks in advance.
did you tried getCssValue from webelement.
for instance: ele.getCssValue("propname")
By the way to check element is displayed or not you should user isDisplayed method of webelement
In webdriver we use
WebElement element = driver.findElement(By.name("elementName"));
and then
String attributeValue = element.getAttribute("attributeName");
So in your case it will
String styleValue = element.getAttribute("style");