Skip to content

Commit 351eb16

Browse files
committed
Added retry logic for finding elements in shadow DOM
1 parent 9fde451 commit 351eb16

File tree

2 files changed

+103
-12
lines changed

2 files changed

+103
-12
lines changed

bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/shadowdom/ShadowDomService.java

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,25 @@
1313

1414
package solutions.bellatrix.playwright.components.shadowdom;
1515

16+
import com.microsoft.playwright.Page;
17+
import lombok.SneakyThrows;
1618
import lombok.experimental.UtilityClass;
19+
import solutions.bellatrix.core.configuration.ConfigurationService;
1720
import solutions.bellatrix.core.utilities.InstanceFactory;
1821
import solutions.bellatrix.core.utilities.Ref;
1922
import solutions.bellatrix.core.utilities.SingletonFactory;
23+
import solutions.bellatrix.core.utilities.Wait;
2024
import solutions.bellatrix.playwright.components.WebComponent;
25+
import solutions.bellatrix.playwright.configuration.WebSettings;
2126
import solutions.bellatrix.playwright.findstrategies.*;
2227
import solutions.bellatrix.playwright.services.JavaScriptService;
2328

29+
import java.time.Duration;
2430
import java.util.ArrayList;
2531
import java.util.List;
2632
import java.util.Stack;
33+
import java.util.concurrent.Callable;
34+
import java.util.function.Consumer;
2735

2836
@UtilityClass
2937
public class ShadowDomService {
@@ -92,16 +100,53 @@ public static <TComponent extends WebComponent, TFindStrategy extends FindStrate
92100
return componentList;
93101
}
94102

103+
@SneakyThrows
95104
private static String[] getAbsoluteCss(ShadowRoot shadowRoot, String locator) {
96-
return ((ArrayList<String>)shadowRoot
97-
.evaluate(String.format("(el, [locator]) => (%s)(el, locator)", javaScript), new Object[] { locator }))
98-
.toArray(String[]::new);
105+
Callable<String[]> js = () -> {
106+
return ((ArrayList<String>)shadowRoot
107+
.evaluate(String.format("(el, [locator]) => (%s)(el, locator)", javaScript), new Object[] { locator }))
108+
.toArray(String[]::new);
109+
};
110+
if (Wait.retry(() -> {
111+
String[] foundElements;
112+
try {
113+
foundElements = js.call();
114+
} catch (Exception e) {
115+
throw new RuntimeException(e);
116+
}
117+
if (foundElements == null || foundElements.length == 0) {
118+
throw new IllegalArgumentException();
119+
}
120+
}, Duration.ofSeconds(ConfigurationService.get(WebSettings.class).getTimeoutSettings().getElementWaitTimeout()), Duration.ofSeconds(1), false)) {
121+
return js.call();
122+
} else {
123+
throw new IllegalArgumentException("No elements inside the shadow DOM were found with the locator: " + locator);
124+
}
99125
}
100126

127+
@SneakyThrows
101128
private static String[] getRelativeCss(ShadowRoot shadowRoot, String locator, String parentLocator) {
102-
return ((ArrayList<String>)shadowRoot
103-
.evaluate(String.format("(el, [locator, parentLocator]) => (%s)(el, locator, parentLocator)", javaScript), new Object[] { locator, parentLocator }))
104-
.toArray(String[]::new);
129+
Callable<String[]> js = () -> {
130+
return ((ArrayList<String>)shadowRoot
131+
.evaluate(String.format("(el, [locator, parentLocator]) => (%s)(el, locator, parentLocator)", javaScript), new Object[] { locator, parentLocator }))
132+
.toArray(String[]::new);
133+
};
134+
135+
if(Wait.retry(() -> {
136+
String[] foundElements;
137+
try {
138+
foundElements = js.call();
139+
} catch (Exception e) {
140+
throw new RuntimeException(e);
141+
}
142+
if (foundElements == null || foundElements.length == 0) {
143+
throw new IllegalArgumentException();
144+
}
145+
}, Duration.ofSeconds(ConfigurationService.get(WebSettings.class).getTimeoutSettings().getElementWaitTimeout()), Duration.ofSeconds(1), false)) {
146+
return js.call();
147+
} else {
148+
throw new IllegalArgumentException("No elements inside the shadow DOM were found with the locator: " + locator);
149+
}
105150
}
106151

107152
private static <TComponent extends WebComponent> TComponent buildMissingShadowRootsAndCreate(Class<TComponent> clazz, ShadowRoot parentComponent, Ref<String> fullCss) {

bellatrix.web/src/main/java/solutions/bellatrix/web/components/shadowdom/ShadowDomService.java

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,29 @@
1313

1414
package solutions.bellatrix.web.components.shadowdom;
1515

16+
import lombok.SneakyThrows;
1617
import lombok.experimental.UtilityClass;
1718
import org.jsoup.Jsoup;
1819
import org.jsoup.nodes.Element;
1920
import org.jsoup.select.Elements;
2021
import org.openqa.selenium.By;
22+
import solutions.bellatrix.core.configuration.ConfigurationService;
2123
import solutions.bellatrix.core.utilities.HtmlService;
2224
import solutions.bellatrix.core.utilities.InstanceFactory;
2325
import solutions.bellatrix.core.utilities.Ref;
26+
import solutions.bellatrix.core.utilities.Wait;
2427
import solutions.bellatrix.web.components.WebComponent;
28+
import solutions.bellatrix.web.configuration.WebSettings;
2529
import solutions.bellatrix.web.findstrategies.CssFindStrategy;
2630
import solutions.bellatrix.web.findstrategies.FindStrategy;
2731
import solutions.bellatrix.web.findstrategies.ShadowXPathFindStrategy;
2832

33+
import java.time.Duration;
2934
import java.util.ArrayList;
3035
import java.util.Arrays;
3136
import java.util.List;
3237
import java.util.Stack;
38+
import java.util.concurrent.Callable;
3339
import java.util.stream.Collectors;
3440

3541
@UtilityClass
@@ -97,16 +103,56 @@ public static <TComponent extends WebComponent, TFindStrategy extends FindStrate
97103
return componentList;
98104
}
99105

106+
@SneakyThrows
100107
private static String[] getAbsoluteCss(ShadowRoot shadowRoot, String locator) {
101-
return shadowRoot.getJavaScriptService()
102-
.<ArrayList<String>>genericExecute(String.format("return (%s)(arguments[0], arguments[1], arguments[2]);", javaScript),
103-
shadowRoot.findElement(), locator, null).toArray(String[]::new);
108+
Callable<String[]> js = () -> {
109+
return shadowRoot.getJavaScriptService()
110+
.<ArrayList<String>>genericExecute(String.format("return (%s)(arguments[0], arguments[1], arguments[2]);", javaScript),
111+
shadowRoot.findElement(), locator, null).toArray(String[]::new);
112+
};
113+
114+
if (Wait.retry(() -> {
115+
String[] foundElements;
116+
try {
117+
foundElements = js.call();
118+
} catch (Exception e) {
119+
throw new RuntimeException(e);
120+
}
121+
122+
if (foundElements == null || foundElements.length == 0) {
123+
throw new IllegalArgumentException();
124+
}
125+
}, Duration.ofSeconds(ConfigurationService.get(WebSettings.class).getTimeoutSettings().getElementWaitTimeout()), Duration.ofSeconds(1), false)) {
126+
return js.call();
127+
} else {
128+
throw new IllegalArgumentException("No elements inside the shadow DOM were found with the locator: " + locator);
129+
}
104130
}
105131

132+
@SneakyThrows
106133
private static String[] getRelativeCss(ShadowRoot shadowRoot, String locator, String parentLocator) {
107-
return shadowRoot.getJavaScriptService()
108-
.<ArrayList<String>>genericExecute(String.format("return (%s)(arguments[0], arguments[1], arguments[2]);", javaScript),
109-
shadowRoot.findElement(), locator, parentLocator).toArray(String[]::new);
134+
Callable<String[]> js = () -> {
135+
return shadowRoot.getJavaScriptService()
136+
.<ArrayList<String>>genericExecute(String.format("return (%s)(arguments[0], arguments[1], arguments[2]);", javaScript),
137+
shadowRoot.findElement(), locator, parentLocator).toArray(String[]::new);
138+
};
139+
140+
if (Wait.retry(() -> {
141+
String[] foundElements;
142+
try {
143+
foundElements = js.call();
144+
} catch (Exception e) {
145+
throw new RuntimeException(e);
146+
}
147+
148+
if (foundElements == null || foundElements.length == 0) {
149+
throw new IllegalArgumentException();
150+
}
151+
}, Duration.ofSeconds(ConfigurationService.get(WebSettings.class).getTimeoutSettings().getElementWaitTimeout()), Duration.ofSeconds(1), false)) {
152+
return js.call();
153+
} else {
154+
throw new IllegalArgumentException("No elements inside the shadow DOM were found with the locator: " + locator);
155+
}
110156
}
111157

112158
private static <TComponent extends WebComponent> TComponent buildMissingShadowRootsAndCreate(Class<TComponent> clazz, ShadowRoot parentComponent, Ref<String> fullCss) {

0 commit comments

Comments
 (0)