Skip to content

Commit 2950733

Browse files
author
Mat Walker
committed
Complete set and get text in Element
1 parent 236365d commit 2950733

File tree

2 files changed

+100
-8
lines changed

2 files changed

+100
-8
lines changed

src/main/java/TeamControlium/Controlium/HTMLElement.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,19 @@ public void enterText(String text,int maxTries,Duration retryInterval) {
443443
}
444444
}
445445

446+
447+
public String getText() {
448+
throwIfUnbound();
449+
return getText(true);
450+
}
451+
public String getText(boolean includeDesendants) {
452+
throwIfUnbound();
453+
return getSeleniumDriver().getText(getUnderlyingWebElement(),includeDesendants,false,false);
454+
}
455+
456+
457+
458+
446459
// MAT CARRY ON HERE WITH 'SelectedItem' (Element.cs)
447460

448461

src/main/java/TeamControlium/Controlium/SeleniumDriver.java

Lines changed: 87 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@
77
import org.apache.commons.lang3.time.StopWatch;
88
import org.junit.jupiter.api.Assertions;
99

10-
import java.io.BufferedReader;
11-
import java.io.File;
12-
import java.io.InputStreamReader;
10+
import java.io.*;
1311
import java.net.ConnectException;
1412
import java.nio.file.Files;
1513
import java.nio.file.Paths;
@@ -29,6 +27,15 @@
2927
import org.openqa.selenium.ie.InternetExplorerDriver;
3028
import org.openqa.selenium.ie.InternetExplorerDriverService;
3129
import org.openqa.selenium.ie.InternetExplorerOptions;
30+
import org.w3c.dom.NodeList;
31+
32+
import javax.swing.text.html.HTMLDocument;
33+
import javax.swing.text.html.HTMLEditorKit;
34+
import javax.swing.text.html.parser.ParserDelegator;
35+
import javax.xml.xpath.XPath;
36+
import javax.xml.xpath.XPathConstants;
37+
import javax.xml.xpath.XPathExpression;
38+
import javax.xml.xpath.XPathFactory;
3239

3340
public class SeleniumDriver {
3441
// CONSTANT FIELDS
@@ -387,7 +394,7 @@ public String getPageTitle() {
387394
//
388395

389396
public boolean isDisplayed(Object webElement) {
390-
if (webElement==null) throw new RuntimeException("Passed webElement null!");
397+
if (webElement==null) throw new RuntimeException("webElement null!");
391398
Logger.WriteLine(Logger.LogLevels.FrameworkDebug, "Get element displayed status using Selenium IWebElement.isDisplayed");
392399
try {
393400
return ((WebElement) webElement).isDisplayed();
@@ -400,7 +407,7 @@ public boolean isDisplayed(Object webElement) {
400407
}
401408
}
402409
public boolean isEnabled(Object webElement) {
403-
if (webElement==null) throw new RuntimeException("Passed webElement null!");
410+
if (webElement==null) throw new RuntimeException("webElement null!");
404411
Logger.WriteLine(Logger.LogLevels.FrameworkDebug, "Get element enabled status using Selenium IWebElement.isEnabled");
405412
try {
406413
return ((WebElement) webElement).isEnabled();
@@ -415,7 +422,7 @@ public boolean isEnabled(Object webElement) {
415422

416423
public void clear(Object webElement)
417424
{
418-
if (webElement==null) throw new RuntimeException("Passed webElement null!");
425+
if (webElement==null) throw new RuntimeException("webElement null!");
419426
Logger.WriteLine(Logger.LogLevels.FrameworkDebug, "Clearing element using Selenium IWebElement.Clear");
420427
try {
421428
((WebElement) webElement).clear();
@@ -435,7 +442,7 @@ public void setText(Object webElement, String text)
435442
//
436443
// A possible need is to wait until text can be entered:-
437444
//IWebElement aa = ElementFindTimeout.Until((b) => { if (IsElementVisible(WebElement) && IsElementEnabled(WebElement)) return WebElement; else { Logger.WriteLn(this, "SetText", "Polling until Text can be entered"); return null; } });
438-
if (webElement==null) throw new RuntimeException("Passed webElement null!");
445+
if (webElement==null) throw new RuntimeException("webElement null!");
439446
text = (text==null)?"":text;
440447
Logger.WriteLine(Logger.LogLevels.FrameworkDebug, "Entering text using Selenium IWebElement SendKeys: [%s].", text);
441448
try {
@@ -450,6 +457,78 @@ public void setText(Object webElement, String text)
450457
}
451458

452459

460+
public String getText(Object webElement,boolean includeDescendantsText, boolean scrollIntoViewFirst, boolean useInnerTextAttribute) {
461+
if (webElement==null) throw new RuntimeException("webElement null!");
462+
//
463+
// This is a bit odd and there are two issues involved but which boil down to a single one. GetText MUST only return text the user can see (or what
464+
// is the point of what we are trying to achive...). So we must ensure we can see the text we are returning. Note that there is one point being
465+
// deliberatly ignored; foreground/background text colour. In an ideal world we should only return text where the colours are sufficiently different
466+
// for a human to read. But, what is sufficient? Should we take into account common colour-blindness issues etc etc etc.... So, just stay simple for
467+
// now and ignore text colours etc....
468+
//
469+
///////
470+
//
471+
// We may want to scroll into view first; Because
472+
// (a) A user would not be able to get/read the text if hidden so if they cannot see it then it would be a bad test that returned hidden text.
473+
// (b) If the element is outside the viewport getText will return an empty string.
474+
//
475+
if (scrollIntoViewFirst) ScrollIntoView(webElement);
476+
///////
477+
//
478+
// We may use innerText rather than TextContent (as the Text() property does). InnerText returns the text being presented to the user
479+
// whereas TextContent returns the raw text in all nodes within the element - irrelevant of whether hidden or not.
480+
//
481+
StringBuilder text = new StringBuilder();
482+
if (includeDescendantsText)
483+
{
484+
if (useInnerTextAttribute)
485+
{
486+
text.append(((WebElement)webElement).getAttribute("innerText"));
487+
Logger.WriteLine(Logger.LogLevels.FrameworkDebug, "Get element text using element innerText attribute: [{0}]", text);
488+
}
489+
else
490+
{
491+
text.append(((WebElement)webElement).getText());
492+
Logger.WriteLine(Logger.LogLevels.FrameworkDebug, "Get element text using Selenium Text property: [{0}]", text);
493+
}
494+
}
495+
else
496+
{
497+
Reader stringReader = new StringReader(((WebElement)webElement).getAttribute("outerHTML"));
498+
HTMLEditorKit htmlKit = new HTMLEditorKit();
499+
HTMLDocument htmlDoc = (HTMLDocument) htmlKit.createDefaultDocument();
500+
HTMLEditorKit.Parser parser = new ParserDelegator();
501+
try {
502+
parser.parse(stringReader, htmlDoc.getReader(0), true);
503+
}
504+
catch (Exception e) {
505+
throw new RuntimeException(String.format("Error parsing HTML from element outerHTML!"),e);
506+
}
507+
508+
XPath xPath = XPathFactory.newInstance().newXPath();
509+
NodeList nl=null;
510+
try {
511+
XPathExpression exp = xPath.compile("/*/text()");
512+
nl = (NodeList)exp.evaluate(htmlDoc,XPathConstants.NODESET);
513+
} catch (Exception e)
514+
{
515+
throw new RuntimeException(String.format("Error with XPath!"),e);
516+
}
517+
518+
for(int index=0;index<nl.getLength();index++) {
519+
text.append(nl.item(index).getTextContent());
520+
}
521+
}
522+
return text.toString();
523+
}
524+
525+
526+
527+
public void ScrollIntoView(Object webElement)
528+
{
529+
Logger.WriteLine(Logger.LogLevels.FrameworkDebug, "Scrolling element in to view using JavaScript injection - [Element].scrollIntoView()");
530+
executeJavaScriptNoReturnData("arguments[0].scrollIntoView();", webElement);
531+
}
453532

454533
//////////// JAVASCRIPT EXECUTION
455534

@@ -492,7 +571,7 @@ public <T> T executeJavaScript(Class<T> type, String script, Object... args)
492571
/// <summary>Injects and executes Javascript in the currently active Selenium browser. If Selenium throws an error, test is aborted.</summary>
493572
/// <param name="script">Javascript that will be injected into the DOM and executed.</param>
494573
/// <param name="args">Any arguments passed in to the Javascript</param>
495-
public void executeJavaScriptNoReturnData(String script, Object[] args)
574+
public void executeJavaScriptNoReturnData(String script, Object... args)
496575
{
497576
Object dummy = executeJavaScript(Object.class,script,args);
498577
}

0 commit comments

Comments
 (0)