Transcripted Summary

In this chapter we'll look at popups and how to interact with them. We'll look at 3 different types of popups: alerts, file uploads, and then also modals.

To get started, we'll click on this JavaScript Alerts link on our test application..



We're going to write a test that clicks on this button, "Click for JS alert."

And let's just go ahead and inspect this so I can show you something.

So, we have this button here, right?



This will make a call to a JavaScript function, which will then show an alert.

When we click on this button, notice here that we have a pop up. This is the JavaScript alert and it says, "I am a JS Alert"

Let's look for this in the DOM.

And we see here that there are no matches found.

That's because this alert is not attached to the DOM.

We have to use a special way to interact with this alert. We'll do that in our test.

We'll go ahead and click on this OK button, and we notice here that we get a result.



We can assert on this result, and we'll write similar tests for the other buttons as well.

Let's get started.


In our HomePage class, I've already created a method to click on the JavaScripts Alerts link from that home page.


public AlertsPage clickJavaScriptAlerts(){

    clickLink("JavaScript Alerts");
    return new AlertsPage(driver);
}

This will return an AlertsPage object.

I have this class already created, AlertsPage.

I've already created our WebDriver for us as well as our constructor.


package pages;

import org.openqa.selenium.WebDriver;

public class AlertsPage {

    private WebDriver driver;

    public AlertsPage(WebDriver driver){
        this.driver = driver;
    }
}

Let's go ahead and create the element for the first button.

We see that we don't have an id or any other identifier.

The only attribute here is the onclick and it's pointing to a function [“jsAlert()”]. But that doesn't really feel like a safe one because this function name could change.

So, let's go ahead with the text of the button and we can write an Xpath for this.

Let's say, "find the button that has the text which equals Click for JS Alert (.//button[text()="Click for JS Alert"]).



And great, we see that we found one element and it's this one, perfect. So, we'll go ahead and create a new By which searches by X path.

I was going to call this object alertButton but that seems a bit confusing because later on when we look at this, we might think that it's a button that's actually on the alert.

So, let's be very clear in our naming and call this, triggerAlertButton.


private By triggerAlertButton = By.xpath(".//button[text()='Click for JS Alert']");

Okay, let's go ahead and create a method to click that button.


public void triggerAlert(){
    driver.findElement(triggerAlertButton).click();
}

Now, once we've clicked this, we know that we're going to get an alert.


Let's create a method to click the “OK” on that alert.

Now again, we can't use driver.findElement to interact with the alert because it's not a WebElement.

What we're going to need to do is say driver and use this switchTo method. The switchTo method will switch from the current context of the DOM to something else.

So, we say switchTo and then we see some more options that we can switch to, one being an alert.



And we see that the alert method will return an Alert object.

Let's go ahead and call that.

Now we have this alert object, and we can say, . and we see multiple options here such as accept, dismiss, getText and sendKeys.



In this case we want to accept, so we go ahead and call it that.


public void acceptAlert(){
    driver.switchTo().alert().accept();
}

Now let's create our test.

So, we go over to the test section. Let's make a new package and we'll call this package “alerts”.

And we'll make a new test class here, and we'll call it AlertTests.

This will extend from the BaseTests class.

We'll go ahead and create a new test method called testAcceptAlert.

We can do a homePage.clickJavaScriptAlerts(), which gives us the AlertsPage, so we can go ahead and assign that to a new variable called alertsPage.

Then from the alertsPage we can say, "Trigger the alert", and then we can say, "Accept the alert."


@Test
public void testAcceptAlert(){
    var alertsPage = homePage.clickJavaScriptAlerts();
    alertsPage.triggerAlert();
    alertsPage.acceptAlert();
}

Now in order to test this, remember that we have this resulting text "You successfuly clicked an alert". So, let's go ahead and add this to our page class.


Looking at this message, I see a little typo on this word.



So, any of us could go and update the-internet project on GitHub to correct this message. And since we're going to add this to our test, then that test will then begin to fail at that point.

I'm glad that this came up because this is something that happens very often in UI automation. It can happen in any type of automation, but it's really common in UI automation. It's because the development of our application is ongoing. Things are going to change. And so, our tests are going to need to be updated when they fail because of things like this.

So, if the application changes in a way that we want it to change, but yet we wrote our test against the application at a certain point, then there's going to be some delta there that we have to deal with.

Sometimes that's going to be an indicator that there's something that was broken in the application itself, and that is what needs to be fixed.

Sometimes it's going to be because the test is written against an outdated version of the application, and therefore the test needs to be updated.

So just keep this in mind.

This is something that comes with test automation. There's no need to think about your test as being flaky or fragile because of this, it's just the nature of the beast.

Okay, we have an id here “result”, so let's just go ahead and copy this and add it to our framework.

In our AlertsPage class, let's go ahead and create another By, and we'll call this one results.


private By results = By.id("result");

Now we create a method to get the result text.


public String getResult(){
    return driver.findElement(results).getText();
}

Okay, so back to our test.

We want to compare the result with the expected String.


assertEquals(alertsPage.getResult(), "You successfuly clicked an alert", "Results text incorrect");

Okay, so let's go ahead and run this and see if it works.

Wonderful, that works.

Let's go ahead and create some more tests for the other types of alerts.


For our next test, let's go ahead and click on this, JS Confirm button.



Let's verify that this text says, "I am a JS Confirm".

Then this time we're going to click this “Cancel” button instead of the "OK".

Let's write this.


Back in the AlertsPage, we're going to make another button, this time for the confirm.


private By triggerConfirmButton = By.xpath(".//button[text()='Click for JS Confirm']");

Then we can create method to triggerConfirm.


public void triggerConfirm(){
    driver.findElement(triggerConfirmButton).click();
}

And we're going to need to create another method.

Instead of accepting the alert, we want to click on that cancel button.

Now this is getting a little bit confusing for me to look at.



And I'm thinking ahead as I write more and more text.

So, this acceptAlert, what does that really mean? It can be confusing.

I want to now preface these methods, so I'm going to actually rename this method.

Instead of saying, "acceptAlert", I want to preface all of these with, "alert_" and then do something like, "clickToAccept".


public void alert_clickToAccept(){
    driver.switchTo().alert().accept();
}

That way it's really clear if I'm interacting with the page, or if I'm interacting with the alert itself.

Okay, I want to do a same type of pattern here, and we're going to see, "clickToDismiss."

The dismiss actually does the negative button.

When we say, driver.switchTo().alert., we have this dismiss method.


public void alert_clickToDismiss(){
    driver.switchTo().alert().dismiss();
}

And the dismiss method is going to click on this cancel button for us.


But remember before we click cancel, we also want to be able to get this text.

So, let's add a method for that too..


public String alert_getText(){
    return driver.switchTo().alert().getText();
}

Okay, now we're ready to write a new test for this one.

Let's go to our AlertTests, and we'll create a new test in here.

This time we want to see it trigger the confirm, and we want to get the text.

Let's go ahead and store that text inside of a variable.


@Test
public void testGetTextFromAlert(){

    var alertsPage = homePage.clickJavaScriptAlerts();
    alertsPage.triggerConfirm();

    String text = alertsPage.alert_getText();
}

Now that we have the text, we can go ahead and dismiss that alert.


alertsPage.alert_clickToDismiss();

Once we've dismissed it, let's go ahead and do the assertion for this text.


@Test
public void testGetTextFromAlert(){

    var alertsPage = homePage.clickJavaScriptAlerts();
    alertsPage.triggerConfirm();

    String text = alertsPage.alert_getText();
    alertsPage.alert_clickToDismiss();

    assertEquals(text, "I am a JS Confirm", "Alert text incorrect");
}

All right, so let's run this one.

Great.


Okay, let's write one more test for the prompt.



We want to click this prompt button and then we want to enter something here, maybe, “TAU Rocks” and click “OK”.



And then we can get this result and verify it.


Let's go back to our framework and we're going to add a method to click this button, as well as a method to enter text into this field.


private By triggerPromptButton = By.xpath(".//button[text()='Click for JS Prompt']");

Then let's make the method to trigger that.


public void triggerPrompt(){
    driver.findElement(triggerPromptButton).click();
}

Okay. And we have the alert methods here, let's add one more to enter the text.


public void alert_setInput(String text){
    driver.switchTo().alert().sendKeys(text);
}

All right let's go ahead and create the test for this.


@Test
public void testSetInputInAlert(){

    var alertsPage = homePage.clickJavaScriptAlerts();
    alertsPage.triggerPrompt();

    String text = "TAU rocks!";
    alertsPage.alert_setInput(text);
    alertsPage.alert_clickToAccept();

    assertEquals(alertsPage.getResult(), text, "Results text incorrect");
}

Okay, let's run this one.

Okay, that failed, let's see why.



It says that it's expecting, "TAU rocks!" but the actual was, "You entered: TAU rocks!" of course.

So, we can update this.

Right here, we'll just put this [“You entered: ”] first, and then append on our text.


 assertEquals(alertsPage.getResult(), "You entered: " + text, "Results text incorrect");

Let's run it again.

Great. So that time it passed, wonderful. Now you see how to deal with JavaScript Alerts.


# AlertTests.java

package alerts;

import base.BaseTests;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;

public class AlertTests extends BaseTests {

    @Test
    public void testAcceptAlert(){

       var alertsPage = homePage.clickJavaScriptAlerts();
       alertsPage.triggerAlert();
       alertsPage.alert_clickToAccept();

       assertEquals(alertsPage.getResult(), "You successfuly clicked an alert", "Results text incorrect");
    }

    @Test
    public void testGetTextFromAlert(){

        var alertsPage = homePage.clickJavaScriptAlerts();
        alertsPage.triggerConfirm();

        String text = alertsPage.alert_getText();
        alertsPage.alert_clickToDismiss();

        assertEquals(text, "I am a JS Confirm", "Alert text incorrect");
    }

    @Test
    public void testSetInputInAlert(){

        var alertsPage = homePage.clickJavaScriptAlerts();
        alertsPage.triggerPrompt();

        String text = "TAU rocks!";
        alertsPage.alert_setInput(text);
        alertsPage.alert_clickToAccept();

        assertEquals(alertsPage.getResult(), "You entered: " + text, "Results text incorrect");
    }
}

# Running Multiple Tests Within a Class

Now this is our first time creating multiple tests within one class.

If I were to run this entire class, this would fail because each one of these tests is trying to click on the JavaScripts Alert link, assuming that we are on the home page.

We're not on the home page when we're done with these tests, so these tests are leaving the application in a bad state.

What we could do is add something in our BaseTests to say, “before any test runs, make sure that it's actually on the home page”.

Let's go ahead and do that.

We’ll add a @BeforeMethod annotated method called goHome which will take us to the home page.


@BeforeMethod
public void goHome(){
    driver.get("https://the-internet.herokuapp.com/");
    homePage = new HomePage(driver);
}

And in our setUp method we’ll add a call to goHome().


@BeforeClass
public void setUp(){
    System.setProperty("webdriver.chrome.driver", "resources/chromedriver");
    driver = new ChromeDriver();
    goHome();
}

And now let's just run the entire class and make sure that this actually works. Beautiful!





Resources



Quiz

The quiz for this chapter can be found in Chapter 7.3