Search code examples
selenium-webdriverselenideselenium-java

Selenium program not running without static wait


There was another StackOverFlow question for which I had to write a program. My program was not working at all. The program is working fine when we debug it. It's failing at other times.

I assumed that it could be due to sync issues. So, changed all my known ExpectedConditions inbuilt methods as well as my own methods but none worked. Once I add a Thread.Sleep() for 1 sec, it worked.

Why is that sleep - customWait(1) required here? Can't we write this program without sleep?

public class Eljur {
    private static WebDriver driver;
    private static final Duration TIMEOUT_DURATION = Duration.ofSeconds(30);

    public static void main(String[] args) {
        driver = new ChromeDriver();
        driver.manage().window().maximize();
        driver.get("https://eljur.ru/login");
        customWait(1);
        findElement(By.cssSelector("div.form-select-button__placeholder")).click();
        findElement(By.cssSelector("input.form-input__input")).sendKeys("Y");
        findElements(By.cssSelector("div.form-select-option")).get(0).click();
        driver.quit();
    }

    public static void customWait(int seconds) {
        try {
            Thread.sleep(seconds * 1000L);
        } catch (Exception ignored) {
        }
    }

    public static WebElement findElement(By by) {
            return waitFor(elementToBeClickable(by));
    }

    public static List<WebElement> findElements(By by) {
            return waitFor(numberOfElementsToBeMoreThan(by,0));
    }

    public static<T> T waitFor(Function<WebDriver,T> function) {
            return new WebDriverWait(driver, TIMEOUT_DURATION)
                    .until(function);
    }
}

Selenide implementation also poses the same problem. Not working without the static wait.

open("https://eljur.ru/login");
Thread.sleep(1000);
$("div.form-select-button__placeholder").shouldBe(enabled).shouldBe(visible).shouldBe(interactable).click();
$("input.form-input__input").sendKeys("Y");
$$("div.form-select-option").get(0).click();
Selenide.closeWebDriver();

Solution

  • I observed that the app you are mentioning here needs to wait for its ssr tasks to finish which can be spotted from a small ssr attribute on one elemnt you can wait on it. The fixed code here as below.

    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.chrome.ChromeDriver;
    import org.openqa.selenium.support.ui.WebDriverWait;
    
    import java.time.Duration;
    import java.util.List;
    import java.util.function.Function;
    
    import static org.openqa.selenium.support.ui.ExpectedConditions.elementToBeClickable;
    import static org.openqa.selenium.support.ui.ExpectedConditions.numberOfElementsToBeMoreThan;
    
    public class Main {
        private static WebDriver driver;
        private static final Duration TIMEOUT_DURATION = Duration.ofSeconds(30);
    
        public static void main(String[] args) {
            driver = new ChromeDriver();
            driver.manage().window().maximize();
            driver.get("https://eljur.ru/login");
            waitFor((iDriver -> findElement(By.cssSelector("astro-island")).getAttribute("ssr")==null));
            findElement(By.cssSelector("div.form-select-button__placeholder")).click();
            findElement(By.cssSelector("input.form-input__input")).sendKeys("Y");
            findElements(By.cssSelector("div.form-select-option")).get(0).click();
            driver.quit();
        }
    
        public static void customWait(int seconds) {
            try {
                Thread.sleep(seconds * 1000L);
            } catch (Exception ignored) {
            }
        }
    
        public static WebElement findElement(By by) {
            return waitFor(elementToBeClickable(by));
        }
    
        public static List<WebElement> findElements(By by) {
            return waitFor(numberOfElementsToBeMoreThan(by, 0));
        }
    
        public static <T> T waitFor(Function<WebDriver, T> function) {
            return new WebDriverWait(driver, TIMEOUT_DURATION)
                    .until(function);
        }
    }```