Skip to content

Commit 236365d

Browse files
author
Mat Walker
committed
Added iframe handling and setText & enterText functionality
1 parent 8cb990b commit 236365d

File tree

2 files changed

+225
-66
lines changed

2 files changed

+225
-66
lines changed

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

Lines changed: 139 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import TeamControlium.Utilities.Logger;
44
import org.apache.commons.lang3.time.StopWatch;
5-
import org.openqa.selenium.WebElement;
5+
//import org.openqa.selenium.WebElement;
66

77
import java.time.Duration;
88
import java.util.HashMap;
@@ -13,7 +13,7 @@
1313
public class HTMLElement {
1414

1515
private ObjectMapping _mappingDetails;
16-
private WebElement _webElement;
16+
private Object _webElement;
1717
private Object _parentElementOrDriver;
1818

1919
private long elementDefaultChangeDeltaTimemS = 200; // Time to wait between samples when checking if an element is changing (IE. moving on screen)
@@ -37,22 +37,31 @@ public String toString() {
3737
public HTMLElement() {
3838
}
3939

40-
public HTMLElement(Object parent, WebElement underlyingWebElement, ObjectMapping mapping) {
40+
public HTMLElement(Object parent, Object underlyingWebElement, ObjectMapping mapping) {
4141
setParentOfThisElement(parent);
4242
setMappingDetails(mapping);
43-
setSeleniumWebElement(underlyingWebElement);
44-
43+
setUnderlyingWebElement(underlyingWebElement);
4544
}
4645

4746

4847
// PROPERTIES
49-
public WebElement getSeleniumnWebElement() {
48+
public String getFriendlyName() {
49+
ObjectMapping objectMapping = getMappingDetails();
50+
51+
if (objectMapping == null) {
52+
return "No mapping details for element!";
53+
} else {
54+
return objectMapping.getFriendlyName();
55+
}
56+
}
57+
58+
public Object getUnderlyingWebElement() {
5059
return _webElement;
5160
}
5261

53-
public WebElement setSeleniumWebElement(WebElement webElement) {
62+
public Object setUnderlyingWebElement(Object webElement) {
5463
_webElement = webElement;
55-
_mappingDetails = new ObjectMapping(null, String.format("Wired directly to Selenium WebElement [%s]", webElement.toString()));
64+
_mappingDetails = new ObjectMapping(null, String.format("Wired directly to underlying UI driver WebElement [%s]", webElement.getClass().getName()));
5665
return _webElement;
5766
} // Manually wiring to WebElement so we have no mapping details!
5867

@@ -115,6 +124,29 @@ public boolean isBoundToAWebElement() {
115124
return (_webElement != null);
116125
}
117126

127+
public boolean isVisible() {
128+
return isVisible(false);
129+
}
130+
131+
public boolean isVisible(boolean checkIfElementIsInViewport) {
132+
throwIfUnbound(); // We need this to be bound to an element!
133+
Logger.WriteLine(Logger.LogLevels.FrameworkInformation, "Verifying if element is visible");
134+
boolean seleniumStatesElementDisplayed = getSeleniumDriver().isDisplayed(_webElement);
135+
136+
if (checkIfElementIsInViewport && seleniumStatesElementDisplayed) {
137+
boolean elementWithinViewport = false;
138+
String sResult = null;
139+
try {
140+
sResult = getSeleniumDriver().executeJavaScript(String.class, "var rect = arguments[0].getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth));", _webElement);
141+
return (sResult.trim().toLowerCase() == "true");
142+
} catch (Exception e) {
143+
throw new RuntimeException(String.format("Exception executing Javascript to find status of element [%s]", getFriendlyName()));
144+
}
145+
} else {
146+
return checkIfElementIsInViewport;
147+
}
148+
}
149+
118150
public boolean isHeightStable(Duration deltaTime) {
119151
return !isAttributeChanging("offsetHeight", deltaTime);
120152
}
@@ -170,7 +202,15 @@ public boolean isPositionStable() {
170202
}
171203

172204
public boolean isElementEnabled() {
173-
return HTMLElement.isElementEnabled(this);
205+
boolean elementEnabled = false;
206+
if (_webElement != null) {
207+
elementEnabled = getSeleniumDriver().isEnabled(_webElement);
208+
Logger.WriteLine(Logger.LogLevels.FrameworkInformation, String.format("Element [%s] enabled = [%s]", getFriendlyName(), (elementEnabled) ? "true" : "false"));
209+
return elementEnabled;
210+
} else {
211+
Logger.WriteLine(Logger.LogLevels.FrameworkInformation, "Element enabled = [Web or element is NULL, returning false]");
212+
return false;
213+
}
174214
}
175215

176216
public Size getSize() {
@@ -195,7 +235,6 @@ public Size getSize() {
195235
return size;
196236
}
197237

198-
199238
private boolean isAttributeChanging(String attributeName, Duration timeDelta) {
200239
boolean isChanging;
201240
try {
@@ -222,7 +261,6 @@ private boolean isAttributeChanging(String attributeName, Duration timeDelta) {
222261
}
223262
}
224263

225-
226264
private boolean isAttributeChanging(String[] attributeNames, Duration timeDelta) {
227265
HashMap<String, String> attributeFirstStates = new HashMap<String, String>();
228266
boolean isChanging;
@@ -260,28 +298,6 @@ private boolean isAttributeChanging(String[] attributeNames, Duration timeDelta)
260298
return false;
261299
}
262300

263-
public boolean isVisible() {
264-
return isVisible(false);
265-
}
266-
267-
public boolean isVisible(boolean checkIfElementIsInViewport) {
268-
throwIfUnbound(); // We need this to be bound to an element!
269-
Logger.WriteLine(Logger.LogLevels.FrameworkInformation, "Verifying if element is visible");
270-
boolean seleniumStatesElementDisplayed = _webElement.isDisplayed();
271-
272-
if (checkIfElementIsInViewport && seleniumStatesElementDisplayed) {
273-
boolean elementWithinViewport = false;
274-
String sResult = null;
275-
try {
276-
sResult = getSeleniumDriver().executeJavaScript(String.class, "var rect = arguments[0].getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth));", _webElement);
277-
return (sResult.trim().toLowerCase() == "true");
278-
} catch (Exception e) {
279-
throw new RuntimeException(String.format("Exception executing Javascript to find status of element [%s]", getFriendlyName()));
280-
}
281-
} else {
282-
return checkIfElementIsInViewport;
283-
}
284-
}
285301

286302

287303
// METHODS
@@ -344,18 +360,95 @@ public HTMLElement findElementAndBind() {
344360
} catch (Exception ex) {
345361
throw new RuntimeException(String.format("Unable to bind element [%s] as child of [%s] (Find Logic [%s])", getMappingDetails().getFriendlyName(), (getParentOfThisElement().getClass() == SeleniumDriver.class) ? "Driver - IE. a Root element" : ((HTMLElement) getParentOfThisElement()).getMappingDetails().getFriendlyName(), getMappingDetails().getOriginalFindLogic()), ex);
346362
}
347-
this.setSeleniumWebElement(foundElement.getSeleniumnWebElement());
363+
this.setUnderlyingWebElement(foundElement.getUnderlyingWebElement());
348364
return this;
349365
}
350366

367+
public void setText(String text) {
368+
setText(text,1,null);}
369+
public void setText(String text,int maxTries) {
370+
setText(text,maxTries,null);}
371+
public void setText(String text,Duration retryInterval) {
372+
setText(text,1,retryInterval);}
373+
public void setText(String text,int maxTries,Duration retryInterval)
374+
{
375+
RuntimeException lastException=null;
376+
throwIfUnbound();
377+
if (maxTries<1) throw new RuntimeException(String.format("Maximum tries [%d]. Cannot be less than 1.",maxTries));
378+
int tryIndex = 0;
379+
Duration interval = (retryInterval==null) ? Duration.ofMillis(200) : retryInterval;
380+
try
381+
{
382+
// Loop until maximum retry count
383+
while (tryIndex++ <= maxTries)
384+
{
385+
try
386+
{
387+
getSeleniumDriver().clear(this.getUnderlyingWebElement());
388+
enterText(text);
389+
if (tryIndex > 1) Logger.WriteLine(Logger.LogLevels.FrameworkDebug, "{0} attempt attempt good.)", tryIndex);
390+
return;
391+
}
392+
catch (ExceptionInvalidElementState e)
393+
{
394+
Thread.sleep(retryInterval.toMillis());
395+
lastException = e;
396+
}
397+
}
398+
throw lastException;
399+
}
400+
catch (Exception e)
401+
{
402+
Logger.WriteLine(Logger.LogLevels.Error, "[%d] failed attempts to set [%s] to text [%s]: %s", tryIndex,this.getMappingDetails(),text,e.getMessage());
403+
throw new RuntimeException(String.format("Attempt [%d] (Max retries reached)",tryIndex),e);
404+
}
405+
}
406+
407+
408+
public void enterText(String text) {
409+
enterText(text,1,null);}
410+
public void enterText(String text,int maxTries) {
411+
enterText(text,maxTries,null);}
412+
public void enterText(String text,Duration retryInterval) {
413+
enterText(text,1,retryInterval);}
414+
public void enterText(String text,int maxTries,Duration retryInterval) {
415+
RuntimeException lastException=null;
416+
throwIfUnbound();
417+
if (maxTries<1) throw new RuntimeException(String.format("Maximum tries [%d]. Cannot be less than 1.",maxTries));
418+
int tryIndex = 0;
419+
Duration interval = (retryInterval==null) ? Duration.ofMillis(200) : retryInterval;
420+
try
421+
{
422+
// Loop until maximum retry count
423+
while (tryIndex++ <= maxTries)
424+
{
425+
try
426+
{
427+
getSeleniumDriver().setText(this.getUnderlyingWebElement(),(text==null)?"":text);
428+
if (tryIndex > 1) Logger.WriteLine(Logger.LogLevels.FrameworkDebug, "{0} attempt attempt good.)", tryIndex);
429+
return;
430+
}
431+
catch (ExceptionInvalidElementState e)
432+
{
433+
Thread.sleep(retryInterval.toMillis());
434+
lastException = e;
435+
}
436+
}
437+
throw lastException;
438+
}
439+
catch (Exception e)
440+
{
441+
Logger.WriteLine(Logger.LogLevels.Error, "[%d] failed attempts to set [%s] to text [%s]: %s", tryIndex,this.getMappingDetails(),text,e.getMessage());
442+
throw new RuntimeException(String.format("Attempt [%d] (Max retries reached)",tryIndex),e);
443+
}
444+
}
351445

352446
// MAT CARRY ON HERE WITH 'SelectedItem' (Element.cs)
353447

354448

355449
private boolean waitForElementStable(StabilityType stabilityType) {
356450
return waitForElementStable(stabilityType, null);
357451
}
358-
359452
private boolean waitForElementStable(StabilityType stabilityType, Duration timeout) {
360453
throwIfUnbound();
361454
boolean didStabilzeBeforeTimeout = false;
@@ -414,16 +507,6 @@ private void throwIfUnbound() {
414507
throw new RuntimeException("Not bound to a Selenium Web Element");
415508
}
416509

417-
public String getFriendlyName() {
418-
ObjectMapping objectMapping = getMappingDetails();
419-
420-
if (objectMapping == null) {
421-
return "No mapping details for element!";
422-
} else {
423-
return objectMapping.getFriendlyName();
424-
}
425-
}
426-
427510
//////////////////// STATICS
428511
/// <summary>Tests if element is currently visible to the user.</summary>
429512
/// <param name="Element">Element to test</param>
@@ -434,22 +517,21 @@ public String getFriendlyName() {
434517
public static boolean isVisible(HTMLElement element) {
435518
return isVisible(element, false);
436519
}
437-
438520
public static boolean isVisible(HTMLElement element, boolean CheckIfElementIsInViewport) {
439521
return element.isVisible(CheckIfElementIsInViewport);
440522
}
441523

442-
public static boolean isElementEnabled(HTMLElement element) {
443-
boolean elementEnabled = false;
444-
if ((element != null) && element.getSeleniumnWebElement() != null) {
445-
elementEnabled = element.getSeleniumnWebElement().isEnabled();
446-
Logger.WriteLine(Logger.LogLevels.FrameworkInformation, String.format("Element [%s] enabled = [%s]", element.getFriendlyName(), (elementEnabled) ? "true" : "false"));
447-
return elementEnabled;
448-
} else {
449-
Logger.WriteLine(Logger.LogLevels.FrameworkInformation, "Element enabled = [Web or element is NULL, returning false]");
450-
return false;
451-
}
452-
}
524+
// public static boolean isElementEnabled(HTMLElement element) {
525+
// boolean elementEnabled = false;
526+
// if ((element != null) && element.getUnderlyingWebElement() != null) {
527+
// elementEnabled = element.getUnderlyingWebElement().isEnabled();
528+
// Logger.WriteLine(Logger.LogLevels.FrameworkInformation, String.format("Element [%s] enabled = [%s]", element.getFriendlyName(), (elementEnabled) ? "true" : "false"));
529+
// return elementEnabled;
530+
// } else {
531+
// Logger.WriteLine(Logger.LogLevels.FrameworkInformation, "Element enabled = [Web or element is NULL, returning false]");
532+
// return false;
533+
// }
534+
// }
453535

454536

455537
}

0 commit comments

Comments
 (0)