简体   繁体   中英

For loop with a size 3 WebElement List clicking on the same link after first instance

I have 3 links within a bento box group in our website. I need to click the specific link if the link text matches my condition (I need to click all the 3 links anyways and I need to perform different actions after clicking them). I wrote if loops within a for loop for achieving this.

When I execute this, for the first loop ie i=0, it clicks on the correct link. For the second loop (i=1), I expect it to pick the second link. But it clicks on the third link. For the third loop as well, it clicks on the third link. Not sure what I am missing here.`

public void SeasonalLinks() throws InterruptedException
{
    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
    List <WebElement> Seasonallnks = driver.findElements(By.xpath("//section[@id='seasonallinks']/ul/li/div/a"));
    int sl = Seasonallnks.size();
    System.out.println("Total no.of seasonal Links: "+sl);
    int i=0;

    for (i=0;i<sl;i++)
    {
        List <WebElement> Seasonallnks1 = driver.findElements(By.xpath("//section[@id='seasonal-links']/ul/li/div/a"));
        String sl1 = Seasonallnks1.get(i).getText();

        if (sl1.equalsIgnoreCase("Start a provider search"))
        {
            Seasonallnks1.get(i).click();
            WebDriverWait pshome = new WebDriverWait(driver,20);
            pshome.until(ExpectedConditions.elementToBeClickable(By.xpath("//li[@id='nav-home']/a[@aria-label='home button']")));
            Thread.sleep(5000);
            driver.findElement(By.xpath("//li[@id='nav-home']/a[@aria-label='home button']")).click();
        }
        else if (sl1.equalsIgnoreCase("Use pharmacy self-service tools"))
        {
            Seasonallnks1.get(i).click();
            WebDriverWait phome = new WebDriverWait(driver,20);
            phome.until(ExpectedConditions.elementToBeClickable(By.xpath("//li[@id='nav-home']/a[@aria-label='home button']")));
            Thread.sleep(5000);
            WebDriverWait iswait1 = new WebDriverWait(driver,30);
            iswait1.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[@class='acc-spinner-container]")));
            driver.findElement(By.xpath("//li[@id='nav-home']/a[@aria-label='home button']")).click();
        }

        else if (sl1.equalsIgnoreCase("Start rewarding yourself today"))
        {
            Seasonallnks1.get(i).click();
            WebDriverWait hhome = new WebDriverWait(driver,20);
            hhome.until(ExpectedConditions.elementToBeClickable(By.xpath("//li[@id='nav-home']/a[@aria-label='home button']")));
            driver.findElement(By.xpath("//li[@id='nav-home']/a[@aria-label='home button']")).click();
        }
    }

Some feedback... to make your code more maintainable and save effort, you should follow the DRY principle (eliminate repetitive code). If you take a look at your if-else chain, there is a lot of repetition there. Each time you click on the same link, wait for an element to be clickable and click it. There's really only one unique thing you do for a single element.

Use of Thread.sleep() should be avoided (google to see a full explanation). You are already using WebDriverWait s, which is a good practice, so add another WebDriverWait to avoid the Thread.sleep() usage, if it's needed.

You have two collections, Seasonallnks and Seasonallnks1 that both store the same elements but the second instance looks like it has a typo in the locator. I combined the two of them.

implicitlyWait() timeout only needs to be set once for the life of the driver and probably should be set outside this function.

The declaration of int i = 0; can/should be done inside the for loop declaration.

You declared two waits but you can reuse the first to make the code more succinct.

If you use a locator more than once, consider declaring it as a variable of type By for easier reuse. It avoids typos and makes it easier to change, when needed, because it only needs to be changed in one place.

wait.until() returns the element(s) waited for so when you wait for an element to be clickable and then intend to click it, you can just add .click() to the end, eg wait.until(...).click();

You should also strive to have more descriptive variable names. It will help you in a few months or someone else that has to read your code and figure out what it's doing.

Hopefully you can see from the cleaned up code below how many lines you can save by using DRY and applying some of the other suggestions I listed above.

public void SeasonalLinks() throws InterruptedException
{
    By seasonalLinksLocator = By.xpath("//section[@id='seasonallinks']/ul/li/div/a");
    List<WebElement> seasonalLinks = driver.findElements(seasonalLinksLocator);
    System.out.println("Total no.of seasonal Links: " + seasonalLinks.size());
    WebDriverWait wait = new WebDriverWait(driver, 20);
    for (int i = 0; i < seasonalLinks.size(); i++)
    {
        String seasonalLinkText = seasonalLinks.get(i).getText();
        seasonalLinks.get(i).click();
        wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//li[@id='nav-home']/a[@aria-label='home button']"))).click();
        if (seasonalLinkText.equalsIgnoreCase("Use pharmacy self-service tools"))
        {
            wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[@class='acc-spinner-container]")));
        }
        seasonalLinks = driver.findElements(seasonalLinksLocator);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM