1

Here is the test Scenario

  • Step 1:- Enter username and password
  • Step 2:- If the user is already logged in, A alert/popup will appear with a logout link and click the link to Logout and try to log in again.

This is the HTML CODE for that alert

<div class="top-alert hidden-xs hidden-sm">
    <div id="alert0" class="alert pull-right alert-danger alert-dismissable" style="display:none;">
        <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
        <strong>Error:</strong> Invalid Inputs!
    </div>
    <div id="alert2" class="alert pull-right alert-warning alert-dismissable" style="display:none;">
        <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
        <strong>Warning:</strong> Your Login is limited
    </div>
    <div id="alert3" class="alert pull-right alert-warning alert-dismissable" style="display:none;">
        <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
        <strong>Warning:</strong> You are Already Loggedin <a href="http://localhost/myapp/public/logout">Logout</a>
    </div>
</div>

And here is the website screenshot

And here is my solution

public class Test
{
    public static void main(String[] args)
    {
        System.setProperty("webdriver.chrome.driver", "C:\\\\Selenium\\\\drivers\\\\chromedriver.exe");
        WebDriver driver = new ChromeDriver();
        driver.get("http://localhost/myapp/public/login");

        // Maxmimize windows
        driver.manage().window().maximize();

        // Login the Tripmaker
        driver.findElement(By.xpath("//input[@id='email']")).sendKeys("test@test.com");
        driver.findElement(By.id("password")).sendKeys("s123456");
        driver.findElement(By.cssSelector("#lsbt")).click();

        // Explicit wait
        if (!driver.findElement(By.xpath("//div[@class='top-alert hidden-xs hidden-sm']/div[@id='alert3']/a[contains(text(), 'Logout')]")).isDisplayed())
        {
            WebDriverWait alert = new WebDriverWait(driver, 5);
            alert.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@class='top-alert hidden-xs hidden-sm']/div[@id='alert3']/a[contains(text(), 'Logout')]")));
            driver.findElement(By.xpath("//div[@class='top-alert hidden-xs hidden-sm']/div[@id='alert3']/a[contains(text(), 'Logout')]")).click();
        }
        else if (driver.findElement(By.xpath("//div[@class='top-alert hidden-xs hidden-sm']/div[@id='alert3']/a[contains(text(), 'Logout')]")).isDisplayed()) 
        {           
            System.out.println("This step is skipped");
        }
    }
}

My code is working but if the alert showed while login its throwing an error

Exception in thread "main" org.openqa.selenium.TimeoutException: Expected condition failed: waiting for visibility of element located by By.xpath: //div[@class='top-alert hidden-xs hidden-sm']/div[@id='alert3']/a[contains(text(), 'Logout')] (tried for 5 second(s) with 500 milliseconds interval)
  at org.openqa.selenium.support.ui.WebDriverWait.timeoutException(WebDriverWait.java:113)
  at org.openqa.selenium.support.ui.FluentWait.until(FluentWait.java:283)
  at demo.myapp.main(myapp.java:41)
Caused by: org.openqa.selenium.NoSuchElementException: Cannot locate an element using By.xpath: //div[@class='top-alert hidden-xs hidden-sm']/div[@id='alert3']/a[contains(text(), 'Logout')]

I Tried .isDisplayed(), .isSelected() and .isEnabled ().

JeffC
  • 22,180
  • 5
  • 32
  • 55
Mrsreez
  • 77
  • 12
  • First of all I would strongly recommend to have a look at the Page-Object-Model. This makes the code much more readable and maintainable. As for your problem: just guessing by the class names: is it possible that the DIV with class "top-alert" changes the classes "hidden-xs" and "hidden-sm" as soon as an alert is shown? – AlvaHenrik Sep 18 '18 at 13:23
  • @JeffC Please don't add `
    ` to the error trace logs as the error trace logs gets truncated and debugging the error trace logs becomes almost impossible.
    – undetected Selenium Sep 18 '18 at 16:21
  • @Newcontributor I've never seen one get truncated due to using blockquote and I've blockquoted or seen some really, really big quotes. I confirmed this one didn't get truncated either. Do you have an example where it gets truncated? – JeffC Sep 18 '18 at 17:35
  • @JeffC I have used the wrong _term_ earlier. Instead of _truncated_ read as _logs get wrapped_. I strongly believe now the example is pretty much self explanatory. – undetected Selenium Sep 18 '18 at 17:43

3 Answers3

1

You can handle popup by try-catch block like this,

try {
      if(driver.findElement(By.id("alert3")).isDisplayed())
      {
      driver.findElement(By.linkText("Logout")).click();
      }
} catch(Exception e) {
      System.out.println("User defined Message");
}
Ishita Shah
  • 3,955
  • 2
  • 27
  • 51
1

As per your usecase to wait for the alert to appear with a logout link and click the link with text as Logout you need to induce WebDriverWait for the element to be clickable and you can use the following code block:

//Login the Tripmaker
driver.findElement(By.xpath("//input[@id='email']")).sendKeys("test@test.com");
driver.findElement(By.id("password")).sendKeys("s123456");
driver.findElement(By.cssSelector("#lsbt")).click();
try {
    new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//div[@class='top-alert hidden-xs hidden-sm']//div[@class='alert pull-right alert-warning alert-dismissable' and @id='alert3']//a[@href='http://localhost/myapp/public/logout']"))).click();
}
catch (TimeoutException e) { 
    System.out.println("Element is not present");
}
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
1

I fixed a few things in your code. You had a mix of By.id(), By.cssSelector(), and By.XPath() all finding elements that have IDs. You should prefer IDs whenever they are available and use By.id(). You also had a lot of extra ifs that weren't necessary. You checked if the element was not visible, then waited for it to be visible, then found it again and clicked on it or else if it's not visible then print a message. All told you ended up finding that element 4 times when you only need to do it once.

Since the element may or may not be there and we need to wait for it, you will need to surround the wait with a try-catch.

public class Test
{
    public static void main(String[] args)
    {
        System.setProperty("webdriver.chrome.driver", "C:\\\\Selenium\\\\drivers\\\\chromedriver.exe");
        WebDriver driver = new ChromeDriver();
        driver.get("http://localhost/myapp/public/login");

        // Maxmimize windows
        driver.manage().window().maximize();

        // Login the Tripmaker
        driver.findElement(By.id("email")).sendKeys("test@test.com");
        driver.findElement(By.id("password")).sendKeys("s123456");
        driver.findElement(By.id("lsbt")).click();

        try
        {
            // wait for the logout link in the dialog and click it
            new WebDriverWait(driver, 3).until(ExpectedConditions.elementToBeClickable(By.cssSelector("#alert3 a[href$='logout']"))).click();
        }
        catch (TimeoutException)
        {
            // logout link was never displayed
            System.out.println("This step is skipped");
        }
    }
}
JeffC
  • 22,180
  • 5
  • 32
  • 55
  • This error is shown **Syntax error, insert "VariableDeclaratorId" to complete FormalParameter** – Mrsreez Sep 18 '18 at 14:35
  • See [this](https://stackoverflow.com/questions/33407415/syntax-error-insert-variabledeclaratorid-to-complete-formalparameterlist). You've got something off in your project. – JeffC Sep 18 '18 at 15:25