Implement global listener to pause code execution
One solution which is a bit more complex than using a listener would be to wrap your element with a proxy and perform the check whenever you hit the proxy.
Let the listeners listen to events and not change the test's flow,
First of all we need to create a class that will perform the check whenever you call the element:
public class ElementProxy implements InvocationHandler { private final WebElement element; public ElementProxy(WebElement element) { this.element = element; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { this.waitForPageLoad(); return method.invoke(element, args); } private void waitForPageLoad() { WebDriver driver = ((WrapsDriver) element).getWrappedDriver(); WebElement loadingBar = driver.findElement(By.xpath("//div[@class='ngx-loading-text center-center' and starts-with(., 'Loading')]")); new WebDriverWait(driver, 20).until(ExpectedConditions.invisibilityOfElement(loadingBar)) } public static WebElement proxy(WebElement element) { ElementProxy proxy = new ElementProxy(element); WebElement wrappdElement = (WebElement) Proxy.newProxyInstance(ElementProxy.class.getClassLoader(), new Class[] { WebElement.class }, proxy); return wrappdElement; } }
Then you can call ElementProxy.proxy(element)
which will return a new proxied element, similar to the behavior of PageFactory
under the hood.Last thing is to wrap it under your own PageFactory
so you can control the behavior of the elements:
public class MyPageFactory { public static <T> void initElements(WebDriver driver, T pageObject) { PageFactory.initElements(driver, pageObject); for (Field field : pageObject.getClass().getDeclaredFields()) { if (field.getType().equals(WebElement.class)) { boolean accessible = field.isAccessible(); field.setAccessible(true); field.set(pageobject, ElementProxy.proxy((WebElement) field.get(pageObject))); field.setAccessible(accessible); } } } }
Now if you are in a web-page where the loading-bar is present, use your new MyPageFactory
, which will perform the check automatically.
If you do not need to perform the check, use the regular PageFactory
.
Reference: https://www.vinsguru.com/selenium-webdriver-how-to-handle-annoying-random-popup-alerts/
There is a WebDriverEventListener
that can accomplish what you want. You could implement this listener such that before each command executed by selenium, the listener checks for the visibilityOfElementLocated(By.xpath("//div[@class='ngx-loading-text center-center' and starts-with(., 'Loading')]")));
, and if so execute your WebDriverWait. Without seeing your code I'm not sure exactly how you'd implement this, but here's a resource with some good examples.