1717
1818package org .openqa .selenium .htmlunit ;
1919
20+ import java .io .IOException ;
21+ import java .io .InputStream ;
22+ import java .io .UncheckedIOException ;
23+ import java .nio .charset .StandardCharsets ;
2024import java .util .ArrayList ;
2125import java .util .Collections ;
2226import java .util .HashMap ;
3337import org .htmlunit .html .HtmlElement ;
3438import org .htmlunit .html .HtmlPage ;
3539import org .openqa .selenium .By ;
40+ import org .openqa .selenium .By .Remotable .Parameters ;
3641import org .openqa .selenium .InvalidSelectorException ;
3742import org .openqa .selenium .NoSuchElementException ;
3843import org .openqa .selenium .WebElement ;
44+ import org .openqa .selenium .support .locators .RelativeLocator ;
45+ import org .openqa .selenium .support .locators .RelativeLocator .RelativeBy ;
3946import org .w3c .dom .Node ;
4047import org .w3c .dom .NodeList ;
4148
@@ -49,6 +56,24 @@ public class HtmlUnitElementFinder {
4956 private static final String INVALIDSELECTIONERROR =
5057 "The xpath expression '%s' selected an object of type '%s' instead of a WebElement" ;
5158
59+ private static final String FIND_ELEMENTS_JS ;
60+
61+ static {
62+ try {
63+ final String location =
64+ String .format (
65+ "/%s/%s" ,
66+ HtmlUnitDriver .class .getPackage ().getName ().replace ("." , "/" ), "findElements.js" );
67+
68+ try (InputStream stream = HtmlUnitDriver .class .getResourceAsStream (location )) {
69+ FIND_ELEMENTS_JS = new String (stream .readAllBytes (), StandardCharsets .UTF_8 );
70+ }
71+ }
72+ catch (final IOException e ) {
73+ throw new UncheckedIOException (e );
74+ }
75+ }
76+
5277 private final Map <Class <? extends By >, HtmlUnitElementLocator > finders_ = new HashMap <>();
5378
5479 HtmlUnitElementFinder () {
@@ -60,6 +85,8 @@ public class HtmlUnitElementFinder {
6085 finders_ .put (By .cssSelector ("a" ).getClass (), new FindByCssSelector ());
6186 finders_ .put (By .tagName ("a" ).getClass (), new FindByTagName ());
6287 finders_ .put (By .xpath ("//a" ).getClass (), new FindByXPath ());
88+
89+ finders_ .put (RelativeLocator .with (By .id ("id" )).getClass (), new FindByRelativeLocator ());
6390 }
6491
6592 public WebElement findElement (final HtmlUnitDriver driver , final By locator ) {
@@ -575,4 +602,27 @@ private static List<WebElement> convertRawDomElementsToWebElements(
575602
576603 return toReturn ;
577604 }
605+
606+ public static class FindByRelativeLocator extends HtmlUnitElementLocator {
607+
608+ public FindByRelativeLocator () {
609+
610+ }
611+
612+ @ Override
613+ public List <WebElement > findElements (final HtmlUnitDriver driver , final By locator ) {
614+ return (List <WebElement >) driver .executeScript (FIND_ELEMENTS_JS , asParameter (locator ));
615+ }
616+
617+ @ Override
618+ public List <WebElement > findElements (final HtmlUnitWebElement element , final By locator ) {
619+ // TODO Auto-generated method stub
620+ return null ;
621+ }
622+
623+ private static Object asParameter (final By locator ) {
624+ final Parameters params = ((RelativeBy ) locator ).getRemoteParameters ();
625+ return Map .of (params .using (), params .value ());
626+ }
627+ }
578628}
0 commit comments