Tutorials

In order to learn more about MrChecker structure, start from Project Organisation section and then check out our fantastic tutorials:

This tutorial will guide you through the series of test which perform basic actions on webpages using MrChecker.

Make sure you already have MrChecker Test Framework installed on your PC. How to install?

Your Product Under Test will be the following website: http://the-internet.herokuapp.com/

Project organization

Importing projects

Every MrChecker project should be imported as a Maven Project.

Example from Eclipse IDE:

1
2

Enter the project path and select projects to import.

3

When the import is finished, update the project structure - ALT + F5

4
Exporting projects

In order to create a new standalone MrChecker project, you can use template-app-under-test and export it to the new folder:

5
6

Create a new folder for the project and enter its path. Select project and files to export:

7

Change project name and other properties, if necessary, in pom.xml file:

8

Then you can import the project to the workspace and create new packages and classes.

Creating new packages
  1. You will need two new packages: one for the new page classes, the other one for test classes:

    • Create a package for page classes

      Open Eclipse
      Use the "Project Explorer" on the left
      Navigate to [your-project] → src/main/java → com.capgemini.mrchecker → selenium
      Right-click on "selenium"
      Click on "New" → New Package
      Name the new package "com.capgemini.mrchecker.selenium.pages.[your-product-name]"
    • Create a package for test classes

      Navigate to [your-project] → src/test/java → com.capgemini.mrchecker → selenium
      Right click on "selenium"
      Click on "New" → New Package
      Name the new package "com.capgemini.mrchecker.selenium.tests.[your-product-name]"

Example:

9
Creating new Page Classes
Navigate to: [your-project] → src/main/java → com.capgemini.mrchecker → selenium.pages.[your-product-name]
Click on "New" → New Class
Enter the name "YourPage"

Every Page Class should extend BasePage class. Import all necessary packages and override all required methods:

  • public boolean isLoaded() - returns true if the page is loaded and false if not

  • public void load() - loads the page

  • public String pageTitle() - returns page title

Example:

 public class MainPage extends BasePage {

    @Override
    public boolean isLoaded() {
        return false;
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Main Page'");
    }

    @Override
    public String pageTitle() {
        return "Main Page Title";
    }
 }
Creating new Test Classes
Navigate to  [your-project] → src/test/java → com.capgemini.mrchecker → selenium.tests.[your-product-name]
Click on "New" → New Class
Enter the name "YourCaseTest"

Test classes should extend BaseTest class, import all necessary packages and override all required methods:

  • public void setUp() - executes before each test

  • public void tearDown() - executes after each test

Optionally, it is also possible to implement the following methods:

  • @BeforeClass public static void setUpBeforeClass() - runs only once before all tests

  • @AfterClass public static void tearDownAfterClass() - runs only once after performing all tests

Every test method has to be signed with "@Test" parameter.

 public class YourCaseTest extends BaseTest {
    private static MainPage mainPage = new MainPage();

    @BeforeClass
    public static void setUpBeforeClass() {
        mainPage.load();
    }

    @AfterClass
    public static void tearDownAfterClass() {

    }

    @Override
    public void setUp() {
        if (!mainPage.isLoaded()) {
            mainPage.load();
        }
    }

    @Override
    public void tearDown() {

    }

    @Test
    public void shouldTestRunWithoutReturningError {

    }
 }
Running Tests

Run the test by right-clicking on the test method → Run as → JUnit test.

Basic Tutorials

Basic Tests
example1

The goal of this test is to open A/B Test subpage and redirect to another website.

Steps:

  1. Open The Internet Main Page

  2. Click A/B Testing link and go to A/B Test subpage

  3. Click Elemental Selenium link and open it in new tab

  4. Switch to Elemental Selenium page and check if it’s loaded

example2
Page Class

Create a Page class for AB Testing page. Override all the required methods:

 public class ABtestPage extends BasePage {

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.ABTEST.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'A/B Test Control' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.ABTEST.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }
 }
How to use Enum?

Similarly as in environmental variables case, create an enum for storing values of subURLs:

 public enum PageSubURLsProjectYEnum {

    BASIC_AUTH("basic_auth"),
    NEW_WINDOW("windows/new"),
    WINDOW("windows"),
    CHECKBOX("checkboxes"),
    CONTEXT_MENU("context_menu"),
    KEY_PRESS("key_presses"),
    DYNAMIC_CONTENT("dynamic_content"),
    HOVERS("hovers"),
    SORTABLE_DATA_TABLES("tables"),
    REDIRECT("redirector"),
    JAVASCRIPT_ALERTS("javascript_alerts"),
    CHALLENGING_DOM("challenging_dom"),
    STATUS_CODES("status_codes"),
    LOGIN("login"),
    ABTEST("abtest"),
    BROKEN_IMAGES("broken_images"),
    DROPDOWN("dropdown"),
    HORIZONTAL_SLIDER("horizontal_slider"),
    DOWNLOAD("download"),
    FORGOT_PASSWORD("forgot_password"),
    FORGOT_PASSWORD_EMAIL_SENT("email_sent"),
    EXIT_INTENT("exit_intent"),
    DYNAMIC_LOADING("dynamic_loading"),
    DISAPPEARING_ELEMENTS("disappearing_elements"),
    DRAG_AND_DROP("drag_and_drop"),
    DYNAMIC_CONTROLS("dynamic_controls"),
    UPLOAD("upload"),
    FLOATING_MENU("floating_menu"),
    FRAMES("frames"),
    GEOLOCATION("geolocation"),
    INFINITE_SCROLL("infinite_scroll"),
    JQUERY_UI("jqueryui/menu"),
    JAVASCRIPT_ERROR("javascript_error"),
    LARGE_AND_DEEP_DOM("large"),
    NESTED_FRAMES("nested_frames"),
    NOTIFICATION_MESSAGE("notification_message"),
    DOWNLOAD_SECURE("download_secure"),
    SHIFTING_CONTENT("shifting_content"),
    SLOW_RESOURCES("slow"),
    TYPOS("typos"),
    WYSIWYGEDITOR("tinymce");

    /*
     * Sub URLs are used as real locations in the test environment
     */
    private String subURL;

    private PageSubURLsProjectYEnum(String subURL) {
        this.subURL = subURL;
    }

    ;

    private PageSubURLsProjectYEnum() {

    }

    @Override
    public String toString() {
        return getValue();
    }

    public String getValue() {
        return subURL;
    }

}

Instead of mapping data from an external file, you can store and access them directly from the enum class:

PageSubURLsProjectYEnum.ABTEST.getValue()
Selector

In this test case you need selector for only one page element:

private static final By elementalSeleniumLinkSelector = By.cssSelector("div > div > a");
Page methods

You need two methods for performing page actions:

     /**
     * Clicks 'Elemental Selenium' link at the bottom of the page.
     *
     * @return ElementalSeleniumPage object.
     */
    public ElementalSeleniumPage clickElementalSeleniumLink() {
        getDriver().findElementDynamic(elementalSeleniumLinkSelector)
                .click();
        getDriver().waitForPageLoaded();
        return new ElementalSeleniumPage();
    }

    /**
     * Switches window to the next one - different than the current.
     */
    public void switchToNextTab() {
        ArrayList<String> tabsList = new ArrayList<String>(getDriver().getWindowHandles());
        getDriver().switchTo()
                .window(tabsList.get(1));
    }
Elemental Selenium Page Class

To return new Elemental Selenium Page object, implement its class. You only need to write basic methods to check if the page is loaded. There is no need to interact with objects on the site:

 public class ElementalSeleniumPage extends BasePage {

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(GetEnvironmentParam.ELEMENTAL_SELENIUM_PAGE.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Elemental Selenium' page.");
        getDriver().get(GetEnvironmentParam.ELEMENTAL_SELENIUM_PAGE.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }
}
Test Class

Create a Test class and write a @Test method to execute the scenario:

 @Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class ABtestingTest extends TheInternetBaseTest {

    private static ABtestPage abTestPage;

    @Test
    public void shouldOpenElementalSeleniumPageWhenClickElementalSeleniumLink() {

        logStep("Click Elemental Selenium link");
        ElementalSeleniumPage elementalSeleniumPage = abTestPage.clickElementalSeleniumLink();

        logStep("Switch browser's tab to newly opened one");
        abTestPage.switchToNextTab();

        logStep("Verify if Elemental Selenium Page is opened");
        assertTrue("Unable to open Elemental Selenium page", elementalSeleniumPage.isLoaded());
    }

}
Assert

Asserts methods are used for creating test pass or fail conditions. The optional first parameter is a message which will be displayed in the test failure description.

  • assertTrue(boolean condition) - test passes if condition returns true

  • assertFalse(boolean condition) - test passes if condition returns false

Also, add the @BeforeClass method to open the tested page:

 @BeforeClass
    public static void setUpBeforeClass() {
        abTestPage = shouldTheInternetPageBeOpened().clickABtestingLink();
        logStep("Verify if ABTest page is opened");
        assertTrue("Unable to open ABTest page", abTestPage.isLoaded());
    }

@BeforeClass method executes only once before all other @Test cases in the class. There is also a possibility to create a @AfterClass method which is performed also once after all @Test cases.

You don’t need to implement @setUp and @tearDown methods because they’re already in TheInternetBaseTest class which you extend.

Categories

You can group tests in categories. It’s useful when running many tests at once. Use this parameter:

@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })

Then create an interface representing each category. Example:

public interface TestsSelenium {
    /* For test which are testing web pages considering UI (user interface) and using selenium webdriver */
}

To run a test from specified category create Test Suite class:

@RunWith(WildcardPatternSuite.class) //search for test files under /src/test/java
@IncludeCategories({ TestsChrome.class }) // search all test files with category TestsChrome.class
@ExcludeCategories({ TestsLocal.class, TestsNONParallel.class }) //exclude all test files with category TestsLocal.class and TestsNONParallel.class
@SuiteClasses({ "../**/*Test.class" }) //search only test files, where file name ends with <anyChar/s>Test.class

public class _TestSuiteChrome {

}

You can run a Test Suite as a JUnit test.

example3

In this test case, the goal is to pass username and password authorization and login to the next page.

Steps:

  1. Open The Internet Main Page

  2. Click on Basic Auth link

  3. Open pop-up login window

  4. Enter valid username and password

  5. Open next subpage and verify if the user logged in successfully.

Page Class

Create a page class which represents Basic Auth subpage after proper login.

example4

Override all the required methods:

public class BasicAuthPage extends BasePage {

    public BasicAuthPage() {

    }

    public BasicAuthPage(String login, String password) {
        this.enterLoginAndPasswordByUrl(login, password);
    }

    @Override
    public boolean isLoaded() {
        return true;
    }

    @Override
    public void load() {
        BFLogger.logDebug("load");
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

In order to verify a login, create a selector to access the visible message.

 private static final By selectorTextMessage = By.cssSelector("#content > div > p");
Then create a method to get message value:

/**
*       Returns message displayed by system after user's log in.
*      @return String object representing message displayed by system after user's log in
*/
    public String getMessageValue() {
                return getDriver().findElementDynamic(selectorTextMessage)
                    .getText();
}

Also, create a method to access the pop-up login window and enter user credentials:

    /**
     * Authenticates user using standard simple authentication popup.
     *
     * @param login    User's login
     * @param password User's password
     * @throws AWTException
     * @throws InterruptedException
     */
    public void enterLoginAndPassword(String login, String password) throws AWTException, InterruptedException {
        Robot rb = new Robot();

        Thread.sleep(2000);

        StringSelection username = new StringSelection(login);
        Toolkit.getDefaultToolkit()
                .getSystemClipboard()
                .setContents(username, null);
        rb.keyPress(KeyEvent.VK_CONTROL);
        rb.keyPress(KeyEvent.VK_V);
        rb.keyRelease(KeyEvent.VK_V);
        rb.keyRelease(KeyEvent.VK_CONTROL);

        rb.keyPress(KeyEvent.VK_TAB);
        rb.keyRelease(KeyEvent.VK_TAB);
        Thread.sleep(2000);

        StringSelection pwd = new StringSelection(password);
        Toolkit.getDefaultToolkit()
                .getSystemClipboard()
                .setContents(pwd, null);
        rb.keyPress(KeyEvent.VK_CONTROL);
        rb.keyPress(KeyEvent.VK_V);
        rb.keyRelease(KeyEvent.VK_V);
        rb.keyRelease(KeyEvent.VK_CONTROL);

        rb.keyPress(KeyEvent.VK_ENTER);
        rb.keyRelease(KeyEvent.VK_ENTER);
        Thread.sleep(2000);
    }
Robot class

Creating a Robot object allows performing basic system actions such as pressing keys, moving the mouse or taking screenshots. In this case, it’s used to paste login and password text from the clipboard using 'Ctrl + V' shortcut, go to the next field using 'Tab' key and submit by clicking 'Enter'.

Toolkit

Static class Toolkit can perform basic window actions such as scrolling to a specified position or moving context between components. In this case, it’s used to set clipboard content to username and password value.

Thread.sleep(long millis)

Web drivers like Selenium perform actions much faster than the normal user. This may cause unexpected consequences e.g. some elements may not be loaded before the driver wants to access them. To avoid this problem you can use Thread.sleep(long millis) to wait given time and let browser load wanted component.

BEWARE: Using Thread.sleep(long millis) is not the recommended approach. Selenium driver gives methods to wait for a specified element to be enabled or visible with a timeout parameter. This is a more stable and effective way. Also, method waitForPageLoaded() will not solve that issue because it only waits for the ready state from the browser while some javascript actions might be performed after that.

Test Class

Create a Test class and write a @Test method to execute the scenario. Save parameters as class fields:

@Category({ TestsLocal.class, TestsNONParallel.class })
public class BasicAuthTest extends TheInternetBaseTest {

    private static BasicAuthPage basicAuthPage;

    private String login    = "admin";
    private String password = "admin";
    private String message  = "Congratulations! You must have the proper credentials.";

    @Test
    public void shouldUserLogInWithValidCredentials() throws InterruptedException, AWTException {
        basicAuthPage = shouldTheInternetPageBeOpened().clickBasicAuthLink();

        logStep("Enter login and password");
        basicAuthPage.enterLoginAndPassword(login, password);

        logStep("Verify if user logged in successfully");
        assertEquals("Unable to login user with valid credentials", message,
            basicAuthPage.getMessageValue());
    }

    @Override
    public void tearDown() {
        logStep("Navigate back to The-Internet page");
        theInternetPage.load();
    }
}

assertEquals(Object expected, Object actual) - test passes if parameters are equal .

Alternative scenario:

There is also a possibility to log in with credentials as a part of URL: http://login:password@the-internet.herokuapp.com/basic_auth

Another page class method:

/**
     * Authenticates user passing credentials into URL.
     *
     * @param login    User's login
     * @param password User's password
     */
    private void enterLoginAndPasswordByUrl(String login, String password) {
        getDriver().get("http://" + login + ":" + password + "@" + "the-internet.herokuapp.com/" +
            PageSubURLsProjectYEnum.BASIC_AUTH.getValue());
    }

Another test class method:

@Test
    public void shouldUserLogInWithValidCredentialsSetInURL() {
        logStep("Enter user's credentials into URL to log in");
        basicAuthPage = new BasicAuthPage(login, password);

        logStep("Verify if user logged in successfully");
        assertEquals("Unable to login user with valid credentials", message,
            basicAuthPage.getMessageValue());
    }

After running test class as a JUnit test, both test cases will be performed.

This test goal is to check the dimensions of broken images on the subpage.

example5

Steps:

  1. Open The Internet Main Page

  2. Click Broken Image link and go to Broken Image subpage

  3. Get the 3 images' dimensions and compare them with expected values

Page Class

In this case, create an array of selectors to access images by index number:

public class BrokenImagePage extends BasePage {

    private static final By[] selectorsImages = { By.cssSelector("div > img:nth-child(2)"),
            By.cssSelector("div > img:nth-child(3)"),
            By.cssSelector("div > img:nth-child(4)") };

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.BROKEN_IMAGES.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Broken Images' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.BROKEN_IMAGES.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Returns an image height in pixels.
     *
     * @param imageIndex An index of given image.
     * @return Height of an image in pixels.
     */
    public int getImageHeight(int imageIndex) {
        return getImageDimension(imageIndex).getHeight();
    }

    /**
     * Returns an image width in pixels.
     *
     * @param imageIndex An index of given image.
     * @return Width of an image in pixels.
     */
    public int getImageWidth(int imageIndex) {
        return getImageDimension(imageIndex).getWidth();
    }

    private Dimension getImageDimension(int imageIndex) {
        return getDriver().findElementDynamic(selectorsImages[imageIndex])
                .getSize();
    }

}
Test Class

Create @Test and @BeforeClass methods. Save expected images' dimensions in class fields:

@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class BrokenImagesTest extends TheInternetBaseTest {

    private static BrokenImagePage brokenImagePage;

    private final int expectedHeight = 90;
    private final int expectedWidth  = 120;

    @BeforeClass
    public static void setUpBeforeClass() {
        brokenImagePage = shouldTheInternetPageBeOpened().clickBrokenImageLink();

        logStep("Verify if Broken Image page is opened");
        assertTrue("Unable to open Broken Image page", brokenImagePage.isLoaded());
    }

    @Test
    public void shouldImageSizesBeEqualToExpected() {
        for (int i = 0; i < 3; i++) {
            logStep("Verify size of image with index: " + i);
            assertEquals("Height of image with index: " + i + " is incorrect", expectedHeight,
                   brokenImagePage.getImageHeight(i));
            assertEquals("Width of image with index: " + i + " is incorrect", expectedWidth,
                   brokenImagePage.getImageWidth(i));
        }
    }

}

The test will pass if every image had the correct width and height.

This case goal is to find out how to create stable selectors.

In the browser’s developer mode, you can see how the page is built. Notice, that buttons' IDs change after click and values in the table haven’t got unique attributes, which might be helpful in order to find them.

example6
DOM - Document Object Model

HTML DOM is a model of the page created by the browser. The page could be represented as the tree of objects. Read more.

To create locators you can use element attributes such as id, class name etc.

It this case, since there are no unique attributes, the best approach is to use HTML document structure and identify page elements by their place in an object hierarchy.

Page Class
public class ChallengingDomPage extends BasePage {

    private final By selectorTableRows   = By.cssSelector(".large-10 > table > tbody > tr");
    private final By selectorFirstButton = By.cssSelector(".large-2.columns > .button:nth-
            child(1)");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.CHALLENGING_DOM.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Challenging DOM' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.CHALLENGING_DOM.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Returns table text content as a list of String objects.
     *
     * @return A list of table values.
     */
    public List<String> getTableValues() {
        return JsoupHelper.findTexts(selectorTableRows);
    }

    /**
     * Clicks top button on the page from available button set.
     */
    public void clickFirstButton() {
        getDriver().elementButton(selectorFirstButton)
                .click();
        getDriver().waitForPageLoaded();
    }

}
Jsoup Helper

Jsoup Helper is the tool which helps to parse HTML document and get searched values. This is especially useful when values are organized in a generic structure such as a table.

JsoupHelper.findTexts(By selector) - this method returns text content of a table as a list of Strings

Test Class

Steps:

  1. Open The Internet Main Page

  2. Click Challenging DOM link and go to Challenging DOM subpage

  3. Get and save table values

  4. Click the first button

  5. Get table values again

  6. Compare table values before and after button click

@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class ChallengingDomTest extends TheInternetBaseTest {

    private static ChallengingDomPage challengingDomPage;

    @BeforeClass
    public static void setUpBeforeClass() {
        challengingDomPage = shouldTheInternetPageBeOpened().clickChallengingDomLink();

        logStep("Verify if Challenging Dom page is opened");
        assertTrue("Unable to open Challenging Dom page", challengingDomPage.isLoaded());
    }

    @Test
    public void shouldValuesInTableCellsStayUnchangedAfterClick() {

        logStep("Get table values (before click any button)");
        List<String> tableValuesBeforeClick = challengingDomPage.getTableValues();

        logStep("Click first button");
        challengingDomPage.clickFirstButton();

        logStep("Get table values (after click first button)");
        List<String> tableValuesAfterClick = challengingDomPage.getTableValues();

        logStep("Verify equality of table values before and after click");
        assertEquals("Values from table cells were changed after click", tableValuesBeforeClick,
                tableValuesAfterClick);
    }

}

Because values in the table don’t change, the test should pass if object locators are solid.

In this example, you will learn how to test checkboxes on the page.

example7

A checkbox is a simple web element which can be selected or unselected by clicking on it.

Steps:

  1. Open The Internet Main Page

  2. Click Checkboxes link and go to Checkboxes page

  3. Test if the first checkbox is unchecked

  4. Select the first checkbox

  5. Test if the first checkbox is checked

  6. Test if the second checkbox is checked

  7. Unselect second checkbox

  8. Test if the second checkbox is unchecked

Page Class

Because both checkboxes are in one form, it’s possible to locate them by one selector and then access each individual one by index.

example8
public class CheckboxesPage extends BasePage {

    private final static By checkboxesFormSelector = By.cssSelector("#checkboxes");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.CHECKBOX.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Checkboxes' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.CHECKBOX.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Verifies if checkbox form is visible on the page.
     *
     * @return true if checkboxes are present and displayed on the page
     */
    public boolean isElementCheckboxesFormVisible() {
        return getDriver().elementCheckbox(checkboxesFormSelector)
                .isDisplayed();
    }

    /**
     * Verifies if given checkbox is selected or not.
     *
     * @param index The index of given checkbox
     * @return true if given checkbox is selected
     */
    public boolean isCheckboxSelected(int index) {
        return getDriver().elementCheckbox(checkboxesFormSelector)
                .isCheckBoxSetByIndex(index);
    }

    /**
     * Selects given checkbox. Unselects, if it is already selected.
     *
     * @param index The index of given checkbox
     */
    public void selectCheckbox(int index) {
        CheckBox checkbox = getDriver().elementCheckbox(checkboxesFormSelector);
        if (isCheckboxSelected(index)) {
            checkbox.unsetCheckBoxByIndex(index);
        } else {
            checkbox.setCheckBoxByIndex(index);
        }
    }

}
CheckBox

CheckBox class contains a method to perform actions on checkboxes such as setting and unsetting or verifying if the specified box is checked. Use method elementCheckbox(By selector) to create CheckBox Object.

Test Class
@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class CheckboxesTest extends TheInternetBaseTest {

    private static CheckboxesPage checkboxesPage;

    @Override
    public void setUp() {
        checkboxesPage = shouldTheInternetPageBeOpened().clickCheckboxesLink();

        logStep("Verify if Checkboxes page is opened");
        assertTrue("Unable to open Checkboxes page", checkboxesPage.isLoaded());
    }

    @Test
    public void shouldCheckboxBeSelectedAfterClick() {

        logStep("Verify if first checkbox is not selected");
        assertFalse("The checkbox is selected", checkboxesPage.isCheckboxSelected(0));

        logStep("Select first checkbox");
        checkboxesPage.selectCheckbox(0);

        logStep("Verify if first checkbox is selected");
        assertTrue("The checkbox is not selected", checkboxesPage.isCheckboxSelected(0));
    }

    @Test
    public void shouldCheckboxBeUnselectedAfterClick() {

        logStep("Verify if second checkbox is selected");
        assertTrue("The checkbox is not selected", checkboxesPage.isCheckboxSelected(1));

        logStep("Select second checkbox");
        checkboxesPage.selectCheckbox(1);

        logStep("Verify if second checkbox is not selected");
        assertFalse("The checkbox is selected", checkboxesPage.isCheckboxSelected(1));
    }

}

After running Test Class both @Test cases will be performed. Before each one, overrode setUp method will be executed.

This case will show how to test changing website content.

example9

After refreshing page (F5) a few times, a new element should appear:

example10

Then, after another couple of refreshes, it should disappear.

You can check in developer mode that Gallery element does not exist in HTML document either, until appearing on the page. The element is created by Javascript.

example11
example12

Steps:

  1. Load The Internet Main Page

  2. Click Disappearing Elements link and go to that subpage

  3. Check if Menu Buttons exist on the page

  4. Refresh the page until a new element appears

  5. Check if Gallery Button exists

  6. Check if the number of buttons equals the expected value

  7. Refresh the page until an element disappears

  8. Check if Gallery Button does not exist

  9. Check if the number of buttons is smaller than before

Page Class
public class DisappearingElementsPage extends BasePage {

    private static final By selectorGalleryMenuButton = By.cssSelector("li > a[href*=gallery]");
    private static final By selectorMenuButtons       = By.cssSelector("li");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.DISAPPEARING_ELEMENTS.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Disappearing Elements' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.DISAPPEARING_ELEMENTS.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Returns a number of WebElements representing menu buttons.
     *
     * @return A number of WebElements.
     */
    public int getNumberOfMenuButtons() {
        return getDriver().findElementDynamics(selectorMenuButtons)
                .size();
    }

    /**
     * Returns WebElement representing disappearing element of menu.
     *
     * @return Disappearing WebElement if visible, null otherwise.
     */
    public WebElement getGalleryMenuElement() {
        return getDriver().findElementQuietly(selectorGalleryMenuButton);
    }

    /**
     * Refreshes web page as many times as it is required to appear/disappear menu button
     * WebElement.
     *
     * @param shouldAppear Determines if element should appear (true) or disappear (false).
     */
    public void refreshPageUntilWebElementAppears(boolean shouldAppear) {
        int numberOfAttempts = 5;
        int counter = 0;
        while (!isVisibilityAsExpected(shouldAppear) || isMaxNumberOfAttemptsReached(counter++,
                numberOfAttempts)) {
            refreshPage();
        }
    }

    /**
     * Verify if visibility of Gallery button is the same as expected
     *
     * @param expected Determines if element should be visible (true) or not visible (false).
     */
    private boolean isVisibilityAsExpected(boolean expected) {
        boolean isVisibilityDifferentThanExpected = isGalleryMenuElementVisible() ^ expected;
        return !isVisibilityDifferentThanExpected;
    }

    private boolean isGalleryMenuElementVisible() {
        boolean result = false;
        WebElement gallery = getGalleryMenuElement();
        if (gallery != null)
            result = gallery.isDisplayed();
        return result;
    }

    private boolean isMaxNumberOfAttemptsReached(int attemptNo, int maxNumberOfAttempts) {
        return attemptNo == maxNumberOfAttempts;
    }

}

findElementQuietly(By selector) works similar as findElementDynamics(By selector) but won’t throw an exception if an element wasn’t found. In this case, the searched WebElement will have a NULL value.

Test Class
@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class DisappearingElementsTest extends TheInternetBaseTest {

    private static final int totalNumberOfMenuButtons = 5;
    private static DisappearingElementsPage disappearingElementsPage;
    private static       int numberOfMenuButtons      = 0;

    @BeforeClass
    public static void setUpBeforeClass() {
        disappearingElementsPage = shouldTheInternetPageBeOpened().clickDisappearingElementsLink();

        logStep("Verify if Disappearing Elements page is opened");
        assertTrue("Unable to open Disappearing Elements page",
                disappearingElementsPage.isLoaded());

        logStep("Verify if menu button elements are visible");
        numberOfMenuButtons = disappearingElementsPage.getNumberOfMenuButtons();
        assertTrue("Unable to display menu", numberOfMenuButtons > 0);
    }

    @Test
    public void shouldMenuButtonElementAppearAndDisappearAfterRefreshTest() {
        logStep("Click refresh button until menu button appears");
        disappearingElementsPage.refreshPageUntilWebElementAppears(true);

        logStep("Verify if menu button element appeared");
        assertNotNull("Unable to disappear menu button element",
                disappearingElementsPage.getGalleryMenuElement());
        assertEquals("The number of button elements after refresh is incorrect",
                totalNumberOfMenuButtons, disappearingElementsPage.getNumberOfMenuButtons());

        logStep("Click refresh button until menu button disappears");
        disappearingElementsPage.refreshPageUntilWebElementAppears(false);

        logStep("Verify if menu button element disappeared");
        assertNull("Unable to appear menu button element",
                disappearingElementsPage.getGalleryMenuElement());
        assertTrue("The number of button elements after refresh is incorrect",
                totalNumberOfMenuButtons > disappearingElementsPage.getNumberOfMenuButtons());
    }

}

assertNull(Objetc object) - test passes if Object returns NULL assertNotNull(Objetc object) - test passes if Object does not return NULL

This case shows how to move draggable elements on the page. image::images/example13.png[]

Try to move A to B position and see what happens. Also, open browser developer mode and see how the DOM changes.

example14

The page can easily be broken. You can try to do so and check how the page structure changed in browser developer mode.

example15

Steps:

  1. Open The Internet Main Page

  2. Click Drag and Drop link and open subpage

  3. Check if the Drag and Drop message is visible

  4. Check if element A is in container A and B in container B

  5. Move element A to position B

  6. Check if element A is in container B and B in container A

  7. Move element B to position A

  8. Again check if element A is in container A and B in container B

Page Class
public class DragAndDropPage extends BasePage {

    private static final By selectorDragAndDropText    = By.cssSelector("div#content h3");
    private static final By selectorAElementContainer  = By.cssSelector("div#column-a");
    private static final By selectorBElementContainer  = By.cssSelector("div#column-b");
    private static final By selectorDescriptionElement = By.cssSelector("header");

    private static final String dndHelperPath = "src/test/resources/js/drag_and_drop_helper.js";

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.DRAG_AND_DROP.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Drag and Drop' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() + PageSubURLsProjectYEnum.DRAG_AND_DROP.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Returns information if drag and drop message is visible or not.
     *
     * @return true if exit drag and drop message was found on web page.
     */
    public boolean isDragAndDropMessageVisible() {
        return getDriver().findElementDynamic(selectorDragAndDropText)
                .isDisplayed();
    }

    /**
     * Verifies if specified element is placed in designated container.
     *
     * @param element WebElement to be verified.
     * @return true if element described as A exists in container A or element B exists in container B, false otherwise.
     */
    public boolean isElementPlacedInCorrectContainer(String element) {
        return getDescriptionElement(findElementByDescription(element)).getText()
                .equals(element);
    }

    private WebElement findElementByDescription(String element) {
        WebElement result;
        switch (element) {
            case "A":
                result = getContainerElement(selectorAElementContainer);
                break;
            case "B":
                result = getContainerElement(selectorBElementContainer);
                break;
            default:
                result = null;
                BFLogger.logDebug("Chosen element doesn't exist on web page");
        }
        return result;
    }

    private WebElement getContainerElement(By container) {
        return getDriver().findElementDynamic(container);
    }

    private WebElement getDescriptionElement(WebElement container) {
        return container.findElement(selectorDescriptionElement);
    }

    /**
     * Drags element to designated container and drops it.
     *
     * @param element         String describing WebElement expected to be dragged.
     * @param from            String describing WebElement representing container of element expected to be dragged.
     * @param destinationDesc String describing WebElement representing destination container where other element will be dragged.
     */
    public void dragElementToPosition(String element, String from, String destinationDesc) {
        WebElement source = findElementByDescription(from);
        WebElement description = getDescriptionElement(source);
        WebElement destination = findElementByDescription(destinationDesc);
        if (description.getText()
                .equals(element))
            dragElement(source, destination);
    }

}

Since HTML5, normal Selenium drag-and-drop action stopped working, thus it’s necessary to execute Javascript which performs the drag-and-drop. To do so, create a JavascriptExecutor object, then read the script from a file drag_and_drop_helper.js and execute it with additional arguments using method executeScript(String script).

An example drag-and-drop solution:

    /**
     * Drags and drops given WebElement to it's destination location.
     * <p>
     * Since HTML5 all Selenium Actions performing drag and drop operations stopped working as expected, e.g.
     * original implementation, which was:
     * <code>
     * BasePage.getAction()
     * .clickAndHold(draggable)
     * .moveToElement(target)
     * .release()
     * .build()
     * .perform();
     * </code>
     * finishes with no effect. For this reason, there is javaScript function used, to make sure that
     * drag and drop operation will be successful.
     * JavaScript function is stored under the following path: 'src/test/resources/js/drag_and_drop_helper.js'.
     * Original source of the script:
     * <a href="https://gist.github.com/rcorreia/2362544">drag_and_drop_helper</a>
     * </p>
     *
     * @param draggable A WebElement to be dragged and dropped.
     * @param target    A destination, where element will be dropped.
     * @see JavascriptExecutor
     * @see Actions
     */
    private void dragElement(WebElement draggable, WebElement target) {
        JavascriptExecutor js;
        INewWebDriver driver = getDriver();
        List<String> fileContent;
        String draggableId = draggable.getAttribute("id");
        String targetId = target.getAttribute("id");
        String script = null;
        if (draggable.getAttribute("draggable")
                .contains("true")) {
            if (driver instanceof JavascriptExecutor) {
                js = (JavascriptExecutor) driver;
                Path path = Paths.get(dndHelperPath);
                try {
                    fileContent = Files.readAllLines(path);
                    script = fileContent.stream()
                            .collect(Collectors.joining());
                } catch (IOException e) {
                    BFLogger.logDebug("Unable to read file content: " + e.getMessage());
                }
                if (script != null && !script.isEmpty()) {
                    String arguments = "$('#%s').simulateDragDrop({ dropTarget: '#%s'});";
                    js.executeScript(script + String.format(arguments, draggableId, targetId));
                }
            }
        }
    }

Drag and Drop helper file:

(function( $ ) {
        $.fn.simulateDragDrop = function(options) {
                return this.each(function() {
                        new $.simulateDragDrop(this, options);
                });
        };
        $.simulateDragDrop = function(elem, options) {
                this.options = options;
                this.simulateEvent(elem, options);
        };
        $.extend($.simulateDragDrop.prototype, {
                simulateEvent: function(elem, options) {
                        /*Simulating drag start*/
                        var type = 'dragstart';
                        var event = this.createEvent(type);
                        this.dispatchEvent(elem, type, event);

                        /*Simulating drop*/
                        type = 'drop';
                        var dropEvent = this.createEvent(type, {});
                        dropEvent.dataTransfer = event.dataTransfer;
                        this.dispatchEvent($(options.dropTarget)[0], type, dropEvent);

                        /*Simulating drag end*/
                        type = 'dragend';
                        var dragEndEvent = this.createEvent(type, {});
                        dragEndEvent.dataTransfer = event.dataTransfer;
                        this.dispatchEvent(elem, type, dragEndEvent);
                },
                createEvent: function(type) {
                        var event = document.createEvent("CustomEvent");
                        event.initCustomEvent(type, true, true, null);
                        event.dataTransfer = {
                                data: {
                                },
                                setData: function(type, val){
                                        this.data[type] = val;
                                },
                                getData: function(type){
                                        return this.data[type];
                                }
                        };
                        return event;
                },
                dispatchEvent: function(elem, type, event) {
                        if(elem.dispatchEvent) {
                                elem.dispatchEvent(event);
                        }else if( elem.fireEvent ) {
                                elem.fireEvent("on"+type, event);
                        }
                }
        });
})(jQuery);
Test Class
@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class DragAndDropTest extends TheInternetBaseTest {

    private static final String ELEMENT_A   = "A";
    private static final String CONTAINER_A = "A";
    private static final String ELEMENT_B   = "B";
    private static final String CONTAINER_B = "B";

    private static DragAndDropPage dragAndDropPage;

    @BeforeClass
    public static void setUpBeforeClass() {
        dragAndDropPage = shouldTheInternetPageBeOpened().clickDragAndDropLink();

        logStep("Verify if Drag And Drop page is opened");
        assertTrue("Unable to open Drag And Drop page", dragAndDropPage.isLoaded());

        logStep("Verify if Drag And Drop message is visible");
        assertTrue("Drag And Drop message is not visible", dragAndDropPage.isDragAndDropMessageVisible());
    }

    @Test
    public void shouldDraggableElementBeMovedAndDropped() {
        logStep("Verify if elements are placed in proper containers");
        assertTrue("Element A doesn't exist in container A", dragAndDropPage.isElementPlacedInCorrectContainer(ELEMENT_A));
        assertTrue("Element B doesn't exist in container B", dragAndDropPage.isElementPlacedInCorrectContainer(ELEMENT_B));

        logStep("Step 7: Drag and drop element A into container B");
        dragAndDropPage.dragElementToPosition(ELEMENT_A, CONTAINER_A, CONTAINER_B);

        logStep("Step 8: Verify if elements are placed in improper containers");
        assertFalse("Element A doesn't exist in container B", dragAndDropPage.isElementPlacedInCorrectContainer(ELEMENT_A));
        assertFalse("Element B doesn't exist in container A", dragAndDropPage.isElementPlacedInCorrectContainer(ELEMENT_B));

        logStep("Drag and drop element B back into container B");
        dragAndDropPage.dragElementToPosition(ELEMENT_A, CONTAINER_B, CONTAINER_A);

        logStep("Verify if elements are placed in proper containers");
        assertTrue("Element A doesn't exist in container A", dragAndDropPage.isElementPlacedInCorrectContainer(ELEMENT_A));
        assertTrue("Element B doesn't exist in container B", dragAndDropPage.isElementPlacedInCorrectContainer(ELEMENT_B));
    }

}

This example shows how to select an element from the dropdown list.

example16

Check in the developer mode how a Dropdown List’s content has been organized.

example17

Notice that the Dropdown Options have different attributes, such as "disabled" or "selected".

Steps:

  1. Open The Internet Main Page

  2. Click the Dropdown link and go to the subpage

  3. Select first dropdown Option

  4. Check if Option 1 is selected

  5. Select second dropdown Option

  6. Check if Option 2 is selected

Page Class
public class DropdownPage extends BasePage {

    private static final By dropdownListSelector = By.cssSelector("#dropdown");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.DROPDOWN.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Dropdown List' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.DROPDOWN.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Selects doropdown's value by given index.
     *
     * @param index Index of option to be selected
     */
    public void selectDropdownValueByIndex(int index) {
        getDriver().elementDropdownList(dropdownListSelector)
                .selectDropdownByIndex(index);
    }

    /**
     * Returns text value of first selected dropdown's option.
     *
     * @return String object representing value of dropdown's option
     */
    public String getSelectedDropdownValue() {
        return getDriver().elementDropdownList(dropdownListSelector)
                .getFirstSelectedOptionText();
    }
}
DropdownListElement class

DropdownListElement is MrChecker’s class, which contains methods for performing the dropdown list of actions:

elementDropdownList() - returns DropdownListElement Object
Test Class
@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class DropdownTest extends TheInternetBaseTest {

    private static final String expectedFirstOptionValue  = "Option 1";
    private static final String expectedSecondOptionValue = "Option 2";
    private static DropdownPage dropdownPage;

    @BeforeClass
    public static void setUpBeforeClass() {
        dropdownPage = shouldTheInternetPageBeOpened().clickDropdownLink();

        logStep("Verify if Dropdown page is opened");
        assertTrue("Unable to open Dropdown page", dropdownPage.isLoaded());
    }

    @Test
    public void shouldGetExpectedDropdownTextOptionAfterSelection() {

        logStep("Select first drodown option");
        dropdownPage.selectDropdownValueByIndex(1);

        logStep("Verify if selected option text is equal to the expected one");
        assertEquals("Selected value is different than expected", expectedFirstOptionValue,
                dropdownPage.getSelectedDropdownValue());

        logStep("Select first drodown option");
        dropdownPage.selectDropdownValueByIndex(2);

        logStep("Verify if selected option text is equal to the expected one");
        assertEquals("Selected value is different than expected", expectedSecondOptionValue,
                dropdownPage.getSelectedDropdownValue());
    }

}

This case shows how to compare dynamic content.

example18

Note that after site refresh, some of the content is different. You can see in the browser’s developer mode how the text and image sources are being changed.

example19

Steps:

  1. Open The Internet Main Page

  2. Click Dynamic Content link and load subpage

  3. Save page images sources and descriptions before the refresh

  4. Refresh page

  5. Save page images sources and it’s descriptions after refresh

  6. Compare page content before and after refresh and verify if it’s different

Page Class
public class DynamicContentPage extends BasePage {

    private static final By imagesLinksSelector        = By.cssSelector("div#content > div.row img");
    private static final By imagesDescriptionsSelector = By.cssSelector("div#content > div.row div.large-10");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.DYNAMIC_CONTENT.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Dynamic Content' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.DYNAMIC_CONTENT.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Returns list of picture descriptions being present on the web page.
     *
     * @return List of String objects representing descriptions
     */
    public List<String> getDescriptions() {
        return new ListElements(imagesDescriptionsSelector).getTextList();
    }

    /**
     * Returns a list of image links being present on the web page.
     *
     * @return List of String objects representing paths to pictures
     */
    public List<String> getImageLinks() {
        return new ListElements(imagesLinksSelector)
                .getList()
                .stream()
                .map(element -> element.getAttribute("src"))
                .collect(Collectors.toList());
    }
}
ListElements

ListElements is MrChecker collection which can store WebElement Objects. Constructing ListElements with cssSelector allows you to store every element on the page which fits the selector. Example methods:

getList() -  returns WebElements list,
getTextList() - returns list of contents of each Element,
getSize() - returns number of stored Elements
In getImageLinks() example it's shown how to get a list of specified Elements' attributes.
Test Class
@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class DynamicContentTest extends TheInternetBaseTest {

    private static DynamicContentPage dynamicContentPage;

    @BeforeClass
    public static void setUpBeforeClass() {
        dynamicContentPage = shouldTheInternetPageBeOpened().clickDynamicContentLink();

        logStep("Verify if Dynamic Content page is opened");
        assertTrue("Unable to open Dynamic Content page", dynamicContentPage.isLoaded());
    }

    @Test
    public void shouldImagesAndDescriptionsDifferAfterRefresh() {

        logStep("Read images and descriptions before refresh");
        List<String> descriptionsBeforeRefresh = dynamicContentPage.getDescriptions();
        List<String> imagesBeforeRefresh = dynamicContentPage.getImageLinks();

        logStep("Refres page");
        dynamicContentPage.refreshPage();
        assertTrue("The Dynamic Content page hasn't been refreshed", dynamicContentPage.isLoaded());

        logStep("Read images and descriptions after refresh");
        List<String> descriptionsAfterRefresh = dynamicContentPage.getDescriptions();
        List<String> imagesAfterRefresh = dynamicContentPage.getImageLinks();

        logStep("Verify if descriptions are different after refresh");
        assertEquals("Different number of descriptions before and after refresh",
                descriptionsAfterRefresh.size(), descriptionsBeforeRefresh.size());

        boolean diversity = false;
        for (int i = 0; i < descriptionsAfterRefresh.size(); i++) {
            if (!descriptionsAfterRefresh.get(i)
                    .equals(descriptionsBeforeRefresh.get(i))) {
                diversity = true;
                break;
            }
        }
        assertTrue("There are no differences between descriptions before and after refresh",
                diversity);

        logStep("Verify if images are different after refresh");
        assertEquals("Different number of descriptions before and after refresh",
                imagesAfterRefresh.size(), imagesBeforeRefresh.size());

        diversity = false;
        for (int i = 0; i < imagesAfterRefresh.size(); i++) {
            if (!imagesAfterRefresh.get(i)
                    .equals(imagesBeforeRefresh.get(i))) {
                diversity = true;
                break;
            }
        }
        assertTrue("There are no differences between images before and after refresh", diversity);
    }
}

In the test method, during differences verification, the goal is to compare every element from the first and second list and find first diversity.

This example shows how to test a page with dynamically loading content. Some elements don’t load during page loading, but during JavaScript execution.

example23

Go to Example 1:

example24

Click "start" and see what happens:

example25

When loading ends, you should see the following message:

example26

In the developer mode, you can see that the element with the "Hello World!" message exists in page DOM but it’s not displayed. However, the loading bar does not exist there - it’s created by JavaScript. The script is also visible in developer mode:

example27

After clicking the "Start" button, the element "Loading" is created by the script, and the "Start" button becomes invisible. When loading ends, "Hello World" message is displayed and the loading bar is hidden. Follow the changes the in developer mode:

example28

Go to example 2: From a user perspective, there is no difference in page functioning. However, in this case the element with the "Hello World!" message does not exist on the page before clicking "Start". It’s created by the script.

example29

After clicking "Start", the element with the loading bar is been created.

example30

After a certain time, the loading bar becomes invisible, and then the script creates "Hello World!" element and displays it.

example31
Page Class
public class DynamicLoadingPage extends BasePage {

    private static final By selectorExampleOneLink     =
            By.cssSelector("a[href*='dynamic_loading/1']");
    private static final By selectorExampleTwoLink     =
            By.cssSelector("a[href*='dynamic_loading/2']");
    private static final By selectorDynamicLoadingText = By.cssSelector("div#content h3");
    private static final By selectorStartButton        = By.cssSelector("div#start button");
    private static final By selectorLoadingBar         = By.cssSelector("div#loading");
    private static final By selectorExampleText        = By.cssSelector("div#finish h4");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.DYNAMIC_LOADING.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Dynamically Loaded Page Elements' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.DYNAMIC_LOADING.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Returns information if dynamic loading message is visible or not.
     *
     * @return true if dynamic loading message was found on web page.
     */
    public boolean isDynamicLoadingMessageVisible() {
        return getDriver().findElementDynamic(selectorDynamicLoadingText)
                .isDisplayed();
    }

    /**
     * Clicks Example 1 link.
     */
    public void clickExampleOneLink() {
        getDriver().findElementDynamic(selectorExampleOneLink)
                .click();
    }

    /**
     * Clicks Example 2 link.
     */
    public void clickExampleTwoLink() {
        getDriver().findElementDynamic(selectorExampleTwoLink)
                .click();
    }

    /**
     * Returns information if Start button is visible or not.
     *
     * @return true if Start button was found on web page.
     */
    public boolean isStartButtonVisible() {
        return getDriver().findElementDynamic(selectorStartButton)
                .isDisplayed();
    }

    /**
     * Clicks Start button.
     */
    public void clickStartButton() {
        getDriver().findElementDynamic(selectorStartButton)
                .click();
    }

    /**
     * Waits until WebElement representing waiting bar disappears and returns example text.
     *
     * @param waitTime The amount of time designated for waiting until waiting bar disappears.
     * @return String representing example's text.
     */
    public String getExampleOneDynamicText(int waitTime) {
        WebDriverWait wait = new WebDriverWait(getDriver(), waitTime);
        wait.until((Function<? super WebDriver, Boolean>)
                ExpectedConditions.invisibilityOfElementLocated(selectorLoadingBar));
        return getDriver().findElementDynamic(selectorExampleText)
                .getText();
    }

    /**
     * Returns example text.
     * <p>
     * Waits until WebElement representing waiting bar disappear. Then waits until example text
     * shows up.
     * And after that returns example text.
     * </p>
     *
     * @param waitTime The amount of time designated for waiting until waiting bar disappears and
     * example text shows.
     * @return String representing example's text.
     */
    public String getExampleTwoDynamicText(int waitTime) {
        WebDriverWait wait = new WebDriverWait(getDriver(), waitTime);
        wait.until((Function<? super WebDriver, Boolean>)
                ExpectedConditions.invisibilityOfElementLocated(selectorLoadingBar));
        wait.until((Function<? super WebDriver, WebElement>)
                ExpectedConditions.visibilityOfElementLocated(selectorExampleText));
        return getDriver().findElementDynamic(selectorExampleText)
                .getText();
    }

}
WebDriverWait

This class performs waiting for actions using Selenium Web Driver:

  • WebDriverWait(WebDriver driver, long timeOutInSeconds) - constructor, first parameter takes WebDriver, in a second you can specify a timeout in seconds. FluentWait method:

  • until(Function<? super T, V> isTrue) - waits until condition function given as parameter returns expected value. If waiting time reaches timeout, it throws timeoutException.

MrChecker implements various condition functions in the ExpectedConditions class :

  • visibilityOfElementLocated(By selector) - returns WebElement if it’s visible

  • invisibilityOfElementLocated(By selector) - returns true if Element under given selector is invisible

WebDriver also has methods which wait for some conditions:

  • waitForElement(By selector)

  • waitForElementVisible(By selector)

  • waitUntilElementClickable(By selector)

It’s possible to write your own condition function e.g.:

  public static ExpectedCondition<Boolean> invisibilityOfElementLocated(final By locator) {
    return new ExpectedCondition<Boolean>() {
      @Override
      public Boolean apply(WebDriver driver) {
        try {
          return !(findElement(locator, driver).isDisplayed());
        } catch (NoSuchElementException e) {
          return true;
        } catch (StaleElementReferenceException e) {
          return true;
        }
      }
    };
  }

Or as a lambda expression:

        WebDriverWait wait = new WebDriverWait(getDriver(), waitTime);
        wait.until((WebDriver driver) -> {
            try {
                return !(driver.findElement(selectorExampleText)
                        .isDisplayed());
            } catch (NoSuchElementException e) {
                return true;
            } catch (StaleElementReferenceException e) {
                return true;
            }
        });
Test Class

Case 1 steps:

  1. Open The Internet Main Page

  2. Click Dynamic Loading link and go to a subpage with examples

  3. Check if the page is loaded and "Dynamically Loaded Page Elements" header is visible

  4. Click Example 1 link and load site

  5. Verify if the "Start" button is visible

  6. Click "Start"

  7. Wait for the loading bar to disappear and check if the displayed message is as it should be

  8. Go back to Dynamic Loading page

Case 2 steps:

  1. Check if the page is loaded and "Dynamically Loaded Page Elements" header is visible

  2. Click Example 2 link and load site

  3. Verify if the "Start" button is visible

  4. Click "Start"

  5. Wait for the loading bar to disappear

  6. Wait for the message to appear and check if it is as it should be

  7. Go back to Dynamic Loading page

@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class DynamicLoadingTest extends TheInternetBaseTest {

    private static final int    EXAMPLE_WAITING_TIME = 30;
    private static final String EXAMPLE_TEXT         = "Hello World!";

    private static DynamicLoadingPage dynamicLoadingPage;

    @BeforeClass
    public static void setUpBeforeClass() {
        dynamicLoadingPage = shouldTheInternetPageBeOpened().clickDynamicLoadingLink();
    }

    @Override
    public void setUp() {

        logStep("Verify if Dynamic Loading page is opened");
        assertTrue("Unable to open Dynamic Loading page", dynamicLoadingPage.isLoaded());

        logStep("Verify if dynamic loading message is visible");
        assertTrue("Dynamic loading message is invisible",
                dynamicLoadingPage.isDynamicLoadingMessageVisible());
    }

    @Test
    public void shouldExampleTextBeDisplayedAterRunExampleOne() {
        logStep("Click Example 1 link");
        dynamicLoadingPage.clickExampleOneLink();

        logStep("Verify if Example 1 link opened content");
        assertTrue("Fail to load Example 1 content", dynamicLoadingPage.isStartButtonVisible());

        logStep("Click Start button");
        dynamicLoadingPage.clickStartButton();

        logStep("Verify if expected text is displayed on the screen");
        assertEquals("Fail to display example text", EXAMPLE_TEXT,
                dynamicLoadingPage.getExampleOneDynamicText(EXAMPLE_WAITING_TIME));
    }

    @Test
    public void shouldExampleTextBeDisplayedAterRunExampleTwo() {
        logStep("Click Example 2 link");
        dynamicLoadingPage.clickExampleTwoLink();

        logStep("Verify if Example 2 link opened content");
        assertTrue("Fail to load Example 2 content", dynamicLoadingPage.isStartButtonVisible());

        logStep("Click Start button");
        dynamicLoadingPage.clickStartButton();

        logStep("Verify if expected text is displayed on the screen");
        assertEquals("Fail to display example text", EXAMPLE_TEXT,
                dynamicLoadingPage.getExampleTwoDynamicText(EXAMPLE_WAITING_TIME));
    }

    @Override
    public void tearDown() {
        logStep("Click back to reset Dynamic Loading page");
        BasePage.navigateBack();
    }

}

Perform both cases running Test Class as JUnit Test.

WARNING: In this example, there is a visible loading bar signalizing that content is loading.On many websites elements are created by scripts without clear communique. This may cause problems with test stability. When your tests aren’t finding page elements, try to add wait functions with a short timeout.

example32

This case shows how to perform mouse actions and test modal windows.

After you move the mouse cursor out of the website, you should see a new window appearing:

example33

Check in the browser’s developer mode if this window exists in Page DOM

example34

Before you move the mouse out, the window exists, but it’s not displayed.

When the mouse is moved, JavaScript changes display attribute. It also hides window after clicking "Close".

example35
Page Class
public class ExitIntentPage extends BasePage {

    private static final String MODAL_WINDOW_HIDDEN           = "display: none;";
    private static final String MODAL_WINDOW_DISPLAYED        = "display: block;";
    private static final String MODAL_WINDOW_STYLE_ATTRIBUTTE = "style";

    private static final By selectorModalWindow            = By.cssSelector("div#ouibounce-modal");
    private static final By selectorExitIntentText         = By.cssSelector("div#content h3");
    private static final By selectorModalWindowTitle       = By.cssSelector("h3");
    private static final By selectorModalWindowCloseButton = By.cssSelector("div.modal-footer > p");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.EXIT_INTENT.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Exit Intent' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.EXIT_INTENT.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Returns information if exit intent message is visible or not.
     *
     * @return true if exit intent message was found on web page.
     */
    public boolean isIntentMessageVisible() {
        return getDriver().findElementDynamic(selectorExitIntentText)
                .isDisplayed();
    }

    /**
     * Returns information if modal window is hidden.
     *
     * @return true if modal window is hidden.
     */
    public boolean isModalWindowHidden() {
        return getDriver().findElementDynamic(selectorModalWindow)
                .getAttribute(MODAL_WINDOW_STYLE_ATTRIBUTTE)
                .equals(MODAL_WINDOW_HIDDEN);
    }

    /**
     * Returns information if modal window is showed on web page.
     *
     * @return true if modal window is displayed.
     */
    public boolean isModalWindowVisible() {
        return getDriver().findElementDynamic(selectorModalWindow)
                .getAttribute(MODAL_WINDOW_STYLE_ATTRIBUTTE)
                .equals(MODAL_WINDOW_DISPLAYED);
    }

    /**
     * Returns information if modal window title is shown and correct.
     *
     * @param expectedValue String representing expected value of modal window's title.
     * @return true if modal window's title is equal to expected value.
     */
    public boolean verifyModalWindowTitle(String expectedValue) {
        return getDriver().elementLabel(new ByChained(selectorModalWindow,
                selectorModalWindowTitle))
                .getText()
                .equals(expectedValue);
    }

    /**
     * Closes modal window by pressing 'close' button.
     */
    public void closeModalWindow() {
        getDriver().elementButton(new ByChained(selectorModalWindow,
                selectorModalWindowCloseButton))
                .click();
    }

    /**
     * Moves mouse pointer to the top middle of screen, then to the centre of screen and
     * again to the top.
     * <p>
     * This move simulates leaving the viewport and encourages the modal to show up. There is
     * java.awt.Robot used
     * to move mouse pointer out of the viewport. There are timeouts used to let the browser detect
     * mouse move.
     * </p>
     *
     * @see java.awt.Robot
     */
    public void moveMouseOutOfViewport() {
        Robot robot;
        Dimension screenSize = getDriver().manage()
                .window()
                .getSize();
        int halfWidth = new BigDecimal(screenSize.getWidth() / 2).intValue();
        int halfHeight = new BigDecimal(screenSize.getHeight() / 2).intValue();

        try {
            robot = new Robot();
            robot.mouseMove(halfWidth, 1);
            getDriver().manage()
                    .timeouts()
                    .implicitlyWait(1, TimeUnit.SECONDS);
            robot.mouseMove(halfWidth, halfHeight);
            getDriver().manage()
                    .timeouts()
                    .implicitlyWait(1, TimeUnit.SECONDS);
            robot.mouseMove(halfWidth, 1);
        } catch (AWTException e) {
            BFLogger.logError("Unable to connect with remote mouse");
            e.printStackTrace();
        }
    }
}
Attributes

Elements on pages have attributes like "id", "class", "name", "style" etc. In order to check them, use method getAttribute(String name). In this case attribute "style" determinates if the element is displayed.

Robot

Robot class can perform mouse movement. Method mouseMove(int x, int y) moves the remote mouse to given coordinates.

Manage Timeouts

manage().timeouts() methods allows you to change WebDriver timeouts values such as:

  • pageLoadTimeout(long time, TimeUnit unit) - the amount of time to wait for a page to load before throwing an exception

  • setScriptTimeout(long time, TimeUnit unit) - the amount of time to wait for finish execution of a script before throwing an exception

  • implicitlyWait(long time, TimeUnit unit) - the amount of time the driver should wait when searching for an element if it is not immediately present. After that time, it throws an exception.

Changing timeouts can improve test stability but can also make them run slower.

Test Class

Steps:

  1. Open The Internet Main Page

  2. Click Exit Intent link and load subpage

  3. Check if the page is loaded and "Exit Intent" message is visible

  4. Verify if Modal Window is hidden

  5. Move mouse out of the viewport

  6. Check if Modal Window is visible

  7. Verify if Modal Window title is correct

  8. Click 'close' button

  9. Again verify if Modal Window is hidden

@Category({ TestsLocal.class, TestsNONParallel.class })
public class ExitIntentTest extends TheInternetBaseTest {

    private static final String MODAL_WINDOW_TITLE = "This is a modal window";

    private static ExitIntentPage exitIntentPage;

    @BeforeClass
    public static void setUpBeforeClass() {
        exitIntentPage = shouldTheInternetPageBeOpened().clickExitIntentLink();

        logStep("Verify if Exit Intent page is opened");
        assertTrue("Unable to open Exit Intent page", exitIntentPage.isLoaded());

        logStep("Verify if exit intent message is visible");
        assertTrue("Exit intent message is not visible", exitIntentPage.isIntentMessageVisible());
    }

    @Test
    public void shouldModalWindowAppearWhenMouseMovedOutOfViewportTest() {

        logStep("Verify if modal window is hidden");
        assertTrue("Fail to hide modal window", exitIntentPage.isModalWindowHidden());

        logStep("Move mouse pointer out of viewport");
        exitIntentPage.moveMouseOutOfViewport();

        logStep("Verify if modal window showed up");
        assertTrue("Fail to show up modal window", exitIntentPage.isModalWindowVisible());

        logStep("Verify if modal window title displays properly");
        assertTrue("Fail to display modal window's title",
                exitIntentPage.verifyModalWindowTitle(MODAL_WINDOW_TITLE.toUpperCase()));

        logStep("Close modal window");
        exitIntentPage.closeModalWindow();

        logStep("Verify if modal window is hidden again");
        assertTrue("Fail to hide modal window", exitIntentPage.isModalWindowHidden());
    }
}

Remember not to move mouse manually during test execution.

example36

This example shows how to check if file downloads properly.

After clicking on one of these links, a specific file should be downloaded to your computer.

Steps:

  1. Open The Internet Main Page

  2. Click on the File Download link and open subpage

  3. Click on "some-file.txt" download link and download file

  4. Check if the file exists in the appropriate folder

  5. Delete the file

  6. Check if the file doesn’t exist in the folder

Page Class
public class FileDownloadPage extends BasePage {

    private static final By selectorSomeFileTxt = By.cssSelector("a[href*=some-file]");

    private final String DOWNLOAD_DIR = System.getProperty("java.io.tmpdir");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.DOWNLOAD.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'File Downloader' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.DOWNLOAD.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Verifies if the chosen file is already downloaded and if not, downloads it .
     * Throws RuntimeException otherwise.
     *
     * @return Downloaded file
     */
    public File downloadTextFile() {
        String nameOfDownloadFile = getNameOfDownloadFile();
        File fileToDownload = new File(DOWNLOAD_DIR + nameOfDownloadFile);

        if (fileToDownload.exists()) {
            throw new RuntimeException("The file that you want to download already exists. "
                    + "Please remove it manually. Path to the file: " + fileToDownload.getPath());
        }

        getDriver().elementButton(selectorSomeFileTxt)
                .click();

        waitForFileDownload(2000, fileToDownload);
        return fileToDownload;
    }

    private void waitForFileDownload(int totalTimeoutInMillis, File expectedFile) {
        FluentWait<WebDriver> wait = new FluentWait<WebDriver>(getDriver())
                .withTimeout(totalTimeoutInMillis, TimeUnit.MILLISECONDS)
                .pollingEvery(200, TimeUnit.MILLISECONDS);

        wait.until((WebDriver wd) -> expectedFile.exists());
    }

    private String getNameOfDownloadFile() {
        String urlToDownload = getDriver().findElementDynamic(selectorSomeFileTxt)
                .getAttribute("href");
        String[] urlHierachy = urlToDownload.split("/");
        return urlHierachy[urlHierachy.length - 1];
    }
}

Use FluentWait class and create an expected condition using a lambda expression to wait until the file downloads.

To perform operations on files, use java File class. To get a file name, find it in download URL.

Test Class
@Category({ TestsLocal.class, TestsNONParallel.class })
public class FileDownloadTest extends TheInternetBaseTest {

    private static FileDownloadPage fileDownloadPage;

    @BeforeClass
    public static void setUpBeforeClass() {
        fileDownloadPage = shouldTheInternetPageBeOpened().clickFileDownloadLink();

        logStep("Verify if File Download page is opened");
        assertTrue("Unable to open File Download page", fileDownloadPage.isLoaded());
    }

    @Test
    public void shouldfileBeDownloaded() {

        logStep("Download the some-file.txt");
        File downloadedFile = fileDownloadPage.downloadTextFile();

        logStep("Verify if downloaded file exists");
        assertTrue("Downloaded file does not exist", downloadedFile.exists());

        logStep("Remove downloaded file");
        downloadedFile.delete();

        logStep("Verify if downloaded file has been removed");
        assertFalse("Downloaded file still exists", downloadedFile.exists());
    }
}
example37

This case shows how to pass through the standard authentication page.

When you enter the correct credentials, you should see the next page:

example38

If user data is wrong, an appropriate message appears:

example39
Page Class
public class FormAuthenticationPage extends BasePage {

    private final static By selectorInputUsername     = By.cssSelector("#username");
    private final static By selectorInputUserPassword = By.cssSelector("#password");
    private final static By selectorLoginMessage      = By.cssSelector("#flash");
    private final static By selectorLoginButton       = By.cssSelector("#login > button > i");
    private final static By selectorLogoutButton      = By.cssSelector("#content > div > a ");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.LOGIN.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Login Page' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() + PageSubURLsProjectYEnum.LOGIN.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Sets user name to designated form's field.
     *
     * @param username String representing a user's name
     * @return FormAuthenticationPage object with user name set to the given one
     */
    public FormAuthenticationPage setUsername(String username) {
        InputTextElement elementInputUsername = new InputTextElement(selectorInputUsername);
        elementInputUsername.clearInputText();
        elementInputUsername.setInputText(username);
        return this;
    }

    /**
     * Sets user password to designated form's field.
     *
     * @param userPassword String representing a user's password
     * @return FormAuthenticationPage object with user's password set to the given one
     */
    public FormAuthenticationPage setUserPassword(String userPassword) {
        InputTextElement elementInputPassword = new InputTextElement(selectorInputUserPassword);
        elementInputPassword.clearInputText();
        elementInputPassword.setInputText(userPassword);
        return this;
    }

    /**
     * Returns login message.
     *
     * @return String object representing the message returned after login operation is performed
     */
    public String getLoginMessageText() {
        return new LabelElement(selectorLoginMessage).getText();
    }

    /**
     * Clicks 'Login' button.
     */
    public void clickLoginButton() {
        new Button(selectorLoginButton).click();
    }

    /**
     * Clicks 'Logout' button.
     */
    public void clickLogoutButton() {
        new Button(selectorLogoutButton).click();
    }
}
InputTextElement

Use methods from this class to perform actions on text fields:

  • clearInputText() - remove all text from selected input field

  • setInputText(String text) - enter given text

LabelElement
  • String getText() method returns visible text from label

TestClass

Prepare six test cases:

  1. Try to login with empty user data and check if the error message appears

  2. Try to login with empty username and valid password and check if the error message appears

  3. Try to login with a valid username and empty password and check if the error message appears

  4. Try to login with invalid username and invalid password and check if the error message appears

  5. Try to login with a valid username and valid password and check if success login message appears, then log out

  6. Try to login with a valid username and valid password and check if success login message appears, then log out and check if success logout message is displayed

Before all tests: Open The Internet Main Page

Before each case: Click on the Form Authentication link and open login page

After each case: Go back to The Internet Main Page

@Category({ TestsLocal.class, TestsNONParallel.class })
public class FormAuthenticationTest extends TheInternetBaseTest {

    private static FormAuthenticationPage formAuthenticationPage;

    private String errorUsernameMessage = "Your username is invalid!\n" + "×";
    private String errorPasswordMessage = "Your password is invalid!\n" + "×";
    private String loginMessage         = "You logged into a secure area!\n" + "×";
    private String logoutMessage        = "You logged out of the secure area!\n" + "×";
    private String emptyUsername        = "";
    private String emptyUserPassword    = "";
    private String validUsername        = "tomsmith";
    private String validPassword        = "SuperSecretPassword!";
    private String randomUsername       = UUID.randomUUID()
            .toString();
    private String randomUserPassword   = UUID.randomUUID()
            .toString();

    @BeforeClass
    public static void setUpBeforeClass() {
        logStep("Open the Url http://the-internet.herokuapp.com/");
        theInternetPage = new TheInternetPage();
        theInternetPage.load();

        logStep("Verify if Url http://the-internet.herokuapp.com/ is opened");
        assertTrue("Unable to load The Internet Page", theInternetPage.isLoaded());
    }

    @Override
    public void setUp() {
        logStep("Click subpage link");
        formAuthenticationPage = theInternetPage.clickFormAuthenticationLink();

        logStep("Verify if subpage is opened");
        assertTrue("The Internet subpage: FormAuthenticationPage was not open", formAuthenticationPage.isLoaded());
    }

    @Test
    public void shouldErrorMessageBeDisplayedWhenUserLogsWithEmptyData() {
        logStep("Log user with empty username and password");
        formAuthenticationPage.setUsername(emptyUsername)
                .setUserPassword(emptyUserPassword)
                .clickLoginButton();
        assertEquals("Unexpectedly user logged in with empty data", errorUsernameMessage,
                formAuthenticationPage.getLoginMessageText());
    }

    @Test
    public void shouldErrorMessageBeDisplayedWhenUserLogsWithEmptyUsernameAndValidPassword() {
        logStep("Log user with empty username and valid password");
        formAuthenticationPage.setUsername(emptyUsername)
                .setUserPassword(validPassword)
                .clickLoginButton();
        assertEquals("Unexpectedly user logged in with empty username", errorUsernameMessage,
                formAuthenticationPage.getLoginMessageText());
    }

    @Test
    public void shouldErrorMessageBeDisplayedWhenUserLogsWithValidUsernameAndEmptyPassword() {
        logStep("Log user with valid username and empty password");
        formAuthenticationPage.setUsername(validUsername)
                .setUserPassword(emptyUserPassword)
                .clickLoginButton();
        assertEquals("Unexpectedly user logged in with empty password", errorPasswordMessage,
                formAuthenticationPage.getLoginMessageText());
    }

    @Test
    public void shouldErrorMessageBeDisplayedWhenUserLogsWithInvalidUsernameAndInvalidPassword() {
        logStep("Log user with invalid username and invalid password");
        formAuthenticationPage.setUsername(randomUsername)
                .setUserPassword(randomUserPassword)
                .clickLoginButton();
        assertEquals("Unexpectedly user logged in with random credentials", errorUsernameMessage,
                formAuthenticationPage.getLoginMessageText());
    }

    @Test
    public void shouldUserLogInWithValidCredentials() {
        logStep("Log user with valid username and valid password");
        formAuthenticationPage.setUsername(validUsername)
                .setUserPassword(validPassword)
                .clickLoginButton();
        assertEquals("Unable to login user with valid credentials", loginMessage,
                formAuthenticationPage.getLoginMessageText());
        logStep("Log out user");
        formAuthenticationPage.clickLogoutButton();
    }

    @Test
    public void shouldUserLogOutAfterProperLogInAndClickLogoutButon() {
        logStep("Log user with valid username and valid password");
        formAuthenticationPage.setUsername(validUsername)
                .setUserPassword(validPassword)
                .clickLoginButton();
        assertEquals("Unable to login user with valid credentials", loginMessage,
                formAuthenticationPage.getLoginMessageText());
        logStep("Log out user");
        formAuthenticationPage.clickLogoutButton();
        assertEquals("User cannot log out after prper log in", logoutMessage,
                formAuthenticationPage.getLoginMessageText());
    }

    @Override
    public void tearDown() {
        logStep("Navigate back to The-Internet page");
        theInternetPage.load();
    }
}

After running Test Class, cases might be performed in a different order.

example40

This example shows how to approach elements dynamically appearing after the user’s action.

Move the mouse over an image to see the additional label.

example41

Labels exist in page DOM all the time but their display attributes change. In this case, there is no JavaScript. Elements' visibility is managed by CSS.

example42
Page Class
public class HoversPage extends BasePage {

    private final static By selectorImages = By.cssSelector("div.figure > img");
    private final static By selectorNames  = By.cssSelector("div.figcaption h5");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.HOVERS.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Hovers' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.HOVERS.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Moves mouse pointer over an image with given index.
     *
     * @param index An index of the picture, where mouse pointer should be moved
     */
    public void hoverOverAvatar(int index) {
        Actions action = new Actions(getDriver());
        WebElement avatarImage = getDriver().findElementDynamics(selectorImages)
                .get(index);
        action.moveToElement(avatarImage)
                .perform();
    }

    /**
     * Returns the information displayed under a picture with given index.
     *
     * @param index An index of the picture, where the information should be read
     * @return String object representing picture's information
     */
    public String getAvatarsInformation(int index) {
        return getDriver().findElementDynamics(selectorNames)
                .get(index)
                .getText();
    }
}
Actions

Actions class contains methods used to execute basic user actions such as mouse moving and clicking or keys sending. Action or actions series will be performed after calling perform() method.

Test Class

Steps:

  1. Open The Internet Main Page

  2. Go to Hovers page

  3. Move mouse over random image

  4. Check if displayed text is equal to expected.

@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class HoversTest extends TheInternetBaseTest {

    private static HoversPage    hoversPage;
    private final String        names[]    = { "name: user1", "name: user2", "name: user3" };

    @BeforeClass
    public static void setUpBeforeClass() {
        hoversPage = shouldTheInternetPageBeOpened().clickHoversLink();

        logStep("Verify if Hovers page is opened");
        assertTrue("Unable to open Hovers page", hoversPage.isLoaded());
    }

    @Test
    public void shouldProperInformationBeDisplayedWhenMousePointerHoveredOverRandomElement() {
        logStep("Hover mouse pointer over random element");
        int randomIndex = new Random().nextInt(names.length);
        hoversPage.hoverOverAvatar(randomIndex);
        assertEquals("Picture's information is different than expected", names[randomIndex],
                hoversPage.getAvatarsInformation(randomIndex));
    }
}

Because in this case the tested content is being chosen randomly, each test run could check a different element.

example43

This case shows how to test pop-up JS alerts.

After clicking one of the buttons, an adequate alert should appear.

example44

Performed action will be displayed under "Result" label.

In developer mode, you can view JavaScript which creates alerts.

example45
Page Class
public class JavaScriptAlertsPage extends BasePage {

    private static final By selectorAlertButton   = By.cssSelector("button[onclick*=jsAlert]");
    private static final By selectorConfirmButton = By.cssSelector("button[onclick*=jsConfirm]");
    private static final By selectorPromptButton  = By.cssSelector("button[onclick*=jsPrompt]");
    private static final By resultLabelSelector   = By.cssSelector("p#result");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.JAVASCRIPT_ALERTS.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'JavaScript Alerts' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.JAVASCRIPT_ALERTS.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Clicks 'JS alert' button.
     */
    public void clickAlertButton() {
        new Button(selectorAlertButton).click();
        WebDriverWait wait = new WebDriverWait(getDriver(), 2);
        wait.until(ExpectedConditions.alertIsPresent());
    }

    /**
     * Clicks 'JS confirm' button.
     */
    public void clickConfirmButton() {
        new Button(selectorConfirmButton).click();
        WebDriverWait wait = new WebDriverWait(getDriver(), 2);
        wait.until(ExpectedConditions.alertIsPresent());
    }

    /**
     * Clicks 'JS prompt' button.
     */
    public void clickPromptButton() {
        new Button(selectorPromptButton).click();
        WebDriverWait wait = new WebDriverWait(getDriver(), 2);
        wait.until(ExpectedConditions.alertIsPresent());
    }

    /**
     * Returns message displayed by popup.
     *
     * @return String object representing message displayed by popup
     */
    public String readResultLabel() {
        return new LabelElement(resultLabelSelector).getText();
    }

    /**
     * Clicks alert's 'OK' button.
     */
    public void clickAlertAccept() {
        getDriver().switchTo()
                .alert()
                .accept();
    }

    /**
     * Clicks alert's 'Cancel' button.
     */
    public void clickAlertDismiss() {
        getDriver().switchTo()
                .alert()
                .dismiss();
    }

    /**
     * Types text into alert's text field.
     *
     * @param text String object sent into alert's text field
     */
    public void writeTextInAlert(String text) {
        getDriver().switchTo()
                .alert()
                .sendKeys(text);
    }
}
alert()

Using switchTo() method you can change processed content. switchTo().alert() allows performing actions on appearing alerts such as accepting, dismissing or entering keys.

Test Class

Before all tests: Open The Internet Main Page and go to JavaScript Alert page

  1. Click JS Alert button, accept alert and check if Result message returns performed an action

  2. Click JS Confirm button, accept alert and check if Result message returns performed action

  3. Click JS Confirm button, dismiss alert and check if Result message returns performed action

  4. Click JS Prompt button, write random text, accept alert and check if Result message returns performed action with written text

  5. Click JS Prompt button, dismiss the alert and check if Result message returns performed action

After each case: Refresh Page

After all tests: Navigate back to The Internet Main Page

@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class JavaScriptAlertsTest extends TheInternetBaseTest {

    private static JavaScriptAlertsPage javaScriptAlertsPage;

    private final String jsAlertCofirmMessage    = "You successfuly clicked an alert";
    private final String jsConfirmConfirmMessage = "You clicked: Ok";
    private final String jsConfirmCancelMessage  = "You clicked: Cancel";
    private final String jsPromptConfirmMessage  = "You entered: ";
    private final String jsPromptCancelMessage   = "You entered: null";
    private final String randomString            = "random";

    @BeforeClass
    public static void setUpBeforeClass() {
        javaScriptAlertsPage = shouldTheInternetPageBeOpened().clickJavaScriptAlertLink();

        logStep("Verify if JavaScript Alerts page is opened");
        assertTrue("Unable to open JavaScript Alerts page", javaScriptAlertsPage.isLoaded());
    }

    @AfterClass
    public static void tearDownAfterClass() {
        logStep("Navigate back to The-Internet page");
        BasePage.navigateBack();
    }

    @Test
    public void shouldJSAlertCloseWithProperMessageAfterPressOkButton() {
        logStep("Click Alert button");
        javaScriptAlertsPage.clickAlertButton();

        logStep("Click 'OK' button on alert");
        javaScriptAlertsPage.clickAlertAccept();

        logStep("Verify returned message");
        assertEquals("Incorrect message returned after click",
                jsAlertCofirmMessage, javaScriptAlertsPage.readResultLabel());
    }

    @Test
    public void shouldJSConfirmCloseWithProperMessageAfterPressOkButton() {
        logStep("Click Confirm button");
        javaScriptAlertsPage.clickConfirmButton();

        logStep("Click 'OK' button on alert");
        javaScriptAlertsPage.clickAlertAccept();

        logStep("Verify returned message");
        assertEquals("Incorrect message returned after click",
                jsConfirmConfirmMessage, javaScriptAlertsPage.readResultLabel());
    }

    @Test
    public void shouldJSConfirmCloseWithProperMessageAfterPressCancelButton() {
        logStep("Click Confirm button");
        javaScriptAlertsPage.clickConfirmButton();

        logStep("Click 'Cancel' button on alert");
        javaScriptAlertsPage.clickAlertDismiss();

        logStep("Verify returned message");
        assertEquals("Incorrect message returned after click",
                jsConfirmCancelMessage, javaScriptAlertsPage.readResultLabel());
    }

    @Test
    public void shouldJSPromptCloseWithProperMessageAfterPressOKButton() {
        logStep("Click Prompt button");
        javaScriptAlertsPage.clickPromptButton();

        logStep("Insert text to alert: " + randomString);
        javaScriptAlertsPage.writeTextInAlert(randomString);

        logStep("Click 'OK' button on alert");
        javaScriptAlertsPage.clickAlertAccept();

        logStep("Verify returned message");
        assertEquals("Incorrect message returned after click",
                jsPromptConfirmMessage + randomString, javaScriptAlertsPage.readResultLabel());
    }

    @Test
    public void shouldJSPromptCloseWithProperMessageAfterPressCancelButton() {
        logStep("Click Prompt button");
        javaScriptAlertsPage.clickPromptButton();

        logStep("Click 'Cancel' button on alert");
        javaScriptAlertsPage.clickAlertDismiss();

        logStep("Verify returned message");
        assertEquals("Incorrect message returned after click",
                jsPromptCancelMessage, javaScriptAlertsPage.readResultLabel());
    }

    @Override
    public void tearDown() {
        logStep("Refresh JavaScriptAlersPage");
        javaScriptAlertsPage.refreshPage();
    }

}
example46

This simple case shows how to test key pressing

This site uses JavaScript to read the key pressed and display its value.

example47
Page Class
public class KeyPressesPage extends BasePage {

    private static final By selectorResult = By.cssSelector("#result");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.KEY_PRESS.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Key Presses' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.KEY_PRESS.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Presses given keyboard key.
     *
     * @param keyToPress Key to be pressed on keyboard
     */
    public void pressKey(String keyToPress) {
        getAction().sendKeys(keyToPress)
                .perform();
    }

    /**
     * Returns information from web page about pressed keyboard key.
     *
     * @return Information from web page about pressed key
     */
    public String getPressedKeyInformation() {
        return getDriver().findElementDynamic(selectorResult)
                .getText();
    }
}
Test Class

Steps:

  1. Open The Internet Main Page

  2. Go to Key Presses site

  3. Press a key

  4. Check if a displayed message contains the pressed key

@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class KeyPressesTest extends TheInternetBaseTest {

    private static KeyPressesPage keyPressesPage;

    private final String keyToBePressed  = "Q";
    private final String expectedMessage = "You entered: Q";

    @BeforeClass
    public static void setUpBeforeClass() {
        keyPressesPage = shouldTheInternetPageBeOpened().clickKeyPressesLink();

        logStep("Verify if Key Presses page is opened");
        assertTrue("Unable to open Key Presses page", keyPressesPage.isLoaded());
    }

    @Test
    public void shouldWebsiteReturnInformationAboutPressedKey() {
        logStep("Press a keyboard key");
        keyPressesPage.pressKey(keyToBePressed);

        logStep("Verify if website give valid information about pressed keyboard key");
        assertEquals("Information about the pressed key is invalid", expectedMessage,
                keyPressesPage.getPressedKeyInformation());
    }
}
example48

This simple example shows how operate on many browser tabs

When you click the link, a new website will be opened in the second tab.

example49
Page Class
public class MultipleWindowsPage extends BasePage {

    private final static By selectorLink = By.cssSelector("#content > div > a");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.WINDOW.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Opening a new window' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.WINDOW.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Clicks 'click here' link.
     *
     * @return NewWindowPage object
     */
    public NewWindowPage clickHereLink() {
        getDriver().findElementDynamic(selectorLink)
                .click();
        getDriver().waitForPageLoaded();
        return new NewWindowPage();
    }
}

You also need a second page class for New Window Page. Implement only the required methods.

public class NewWindowPage extends BasePage {

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.NEW_WINDOW.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'New window' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.NEW_WINDOW.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }
}
Test Class

Steps:

  1. Open The Internet Main Page

  2. Go to Multiple Windows Page

  3. Click the link

  4. Check if a new page is opened in the second tab

@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class MultipleWindowsTest extends TheInternetBaseTest {

    private static MultipleWindowsPage    multipleWindowsPage;
    private static NewWindowPage        newWindowPage;

    @BeforeClass
    public static void setUpBeforeClass() {
        multipleWindowsPage = shouldTheInternetPageBeOpened().clickmultipleWindowsLink();

        logStep("Verify if Multiple Windows page is opened");
        assertTrue("Unable to open Multiple Windows page", multipleWindowsPage.isLoaded());
    }

    @Test
    public void verifyIfNewBrowserWindowOpen() {
        logStep("Click 'Click here' link");
        newWindowPage = multipleWindowsPage.clickHereLink();

        logStep("Verify if 'New window page' is opened");
        assertTrue("Unable to open a new browser window", newWindowPage.isLoaded());
    }
}
example50

This simple case shows how to approach redirecting links.

After clicking on the link, you will be redirected to Status Codes Page.

example51
Page Class
Redirect Link Page
public class RedirectLinkPage extends BasePage {

    private static final By selectorRedirectHere = By.cssSelector("a#redirect");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.REDIRECT.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Redirection' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.REDIRECT.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Clicks 'Redirect here' link.
     *
     * @return StatusCodesHomePage object
     */
    public StatusCodesHomePage clickRedirectHereLink() {
        new Button(selectorRedirectHere).click();
        return new StatusCodesHomePage();
    }
}
Status Codes Page
public class StatusCodesHomePage extends BasePage {

    private static final By selectorLink200Code = By.linkText("200");
    private static final By selectorLink301Code = By.linkText("301");
    private static final By selectorLink404Code = By.linkText("404");
    private static final By selectorLink500Code = By.linkText("500");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.STATUS_CODES.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Status Codes' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.STATUS_CODES.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }
}
Test Class

Steps:

  1. Open The Internet Main Page

  2. Go to Redirection Page

  3. Click the link

  4. Check if Status Codes Page is loaded

@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class RedirectLinkTest extends TheInternetBaseTest {

    private static RedirectLinkPage    redirectLinkPage;
    private static StatusCodesHomePage statusCodesHomePage;

    @BeforeClass
    public static void setUpBeforeClass() {
        redirectLinkPage = shouldTheInternetPageBeOpened().clickRedirectLink();

        logStep("Verify if Redirect Link page is opened");
        assertTrue("Unable to open Redirect Link page", redirectLinkPage.isLoaded());
    }

    @Test
    public void shouldUserBeRedirectedToStatusCodePage() {
        logStep("Click 'Redirect here' link");
        statusCodesHomePage = redirectLinkPage.clickRedirectHereLink();

        logStep("Verify redirection to Status Code page");
        assertTrue("User hasn't been redirected to the expected website",
                statusCodesHomePage.isLoaded());
    }
}
example52

This case shows how to move horizontal slider.

You can move the slider by dragging it with a mouse or using arrow keys. The page uses a simple script to get slider position and display set value.

example53
Page Class
public class HorizontalSliderPage extends BasePage {

    private static final By selectorHorizontalSlider = By.cssSelector("div.sliderContainer");
    private static final By sliderSelector           = By.cssSelector("input");
    private static final By valueSelector            = By.cssSelector("#range");

    private HorizontalSliderElement horizontalSlider;

    public HorizontalSliderPage() {
        horizontalSlider = getDriver().elementHorizontalSlider(selectorHorizontalSlider,
                sliderSelector, valueSelector, BigDecimal.ZERO, new BigDecimal(5),
                new BigDecimal(0.5));
    }

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.HORIZONTAL_SLIDER.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Horizontal Slider' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.HORIZONTAL_SLIDER.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Validates if WebElement representing horizontal slider is visible on the page.
     *
     * @return true if horizontal slider is visible, false otherwise.
     */
    public boolean isElementHorizontalSliderVisible() {
        return getDriver().elementHorizontalSlider(selectorHorizontalSlider)
                .isDisplayed();
    }

    /**
     * Returns the value of slider's start position.
     *
     * @return BigDecimal representing the lowest possible value of slider.
     */
    public BigDecimal getStartPosition() {
        return horizontalSlider.getMinRange();
    }

    /**
     * Returns the value of slider's middle position.
     *
     * @return BigDecimal representing the average value between start and end position.
     */
    public BigDecimal getMiddlePosition() {
        return horizontalSlider.getMaxRange()
                .subtract(horizontalSlider.getMinRange())
                .divide(new BigDecimal(2));
    }

    /**
     * Returns the value of slider's end position.
     *
     * @return BigDecimal representing the highest possible value of slider.
     */
    public BigDecimal getEndPosition() {
        return horizontalSlider.getMaxRange();
    }

    /**
     * Returns current value of slider's position.
     *
     * @return BigDecimal representing current value of slider.
     */
    public BigDecimal getCurrentPosition() {
        return horizontalSlider.getCurrentSliderValue();
    }

    /**
     * Sets horizontal slider to a given position using one of the available methods: using keyboard
     * or using mouse move.
     *
     * @param position
     * @param method
     */
    public void setSliderPositionTo(BigDecimal position, int method) {
        horizontalSlider.setSliderPositionTo(position, method);
    }

    /**
     * Verifies the correctness of the given position value and rounds it when necessary.
     *
     * @param position
     * @return Correct value of horizontal slider's position.
     */
    public BigDecimal verifyAndCorrectPositionValue(BigDecimal position) {
        return horizontalSlider.verifyAndCorrectPositionValue(position);
    }
}
Horizontal Slider Element

This class implements methods wich can perform actions on slider:

Create Slider Object using method:

  • getDriver().elementHorizontalSlider(By sliderContainerSelector, By sliderSelector, By valueSelector, BigDecimal minRange, BigDecimal maxRange, BigDecimal step)

And use:

  • BigDecimal getMaxRange()

  • BigDecimal getMinRange()

  • BigDecimal getCurrentSliderValue()

  • setSliderPositionTo(BigDecimal position, int method) - moves slider to a given position. If the position is not valid, it changes it to the nearest proper value. Second parameter determinates movement method: 0 - Keyboard, 1 - Mouse

  • BigDecimal verifyAndCorrectPositionValue(BigDecimal position) - returns nearest correct position

Test Class

Before all tests: Open The Internet Main Page

Before each case:

  1. Go to Horizontal Slider Page

  2. Check if the slider is visible

  3. Save start, middle and end position

Case 1 - Moving with the keyboard:

  1. Move slider to start position, and check if the current position equals the beginning value

  2. Move the slider to middle position, and check if the current position equals the middle value

  3. Move slider to end position, and check if the current position equals the end value

  4. Try to move slider before start position, and check if the current position equals the beginning value

  5. Try to move slider after end position, and check if the current position equals the end value

  6. Try to move the slider to an improperly defined position between start and middle, and check if the current position equals the corrected value

  7. Try to move the slider to an improperly defined random position, and check if the current position equals the corrected value

  8. Move the slider back to start position, and check if the current position equals the beginning value

Case 2 - Moving with a mouse: Repeat each Case 1 step using a mouse instead of keyboard

@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class SliderTest extends TheInternetBaseTest {

    private static HorizontalSliderPage horizontalSliderPage;

    BigDecimal startPosition;
    BigDecimal middlePosition;
    BigDecimal endPosition;

    @BeforeClass
    public static void setUpBeforeClass() {
        logStep("Open the Url http://the-internet.herokuapp.com/");
        theInternetPage = new TheInternetPage();
        theInternetPage.load();

        logStep("Verify if Url http://the-internet.herokuapp.com/ is opened");
        assertTrue("Unable to load The Internet Page", theInternetPage.isLoaded());
    }

    @Override
    public void setUp() {
        logStep("Click Horizontal Slider link");
        horizontalSliderPage = theInternetPage.clickHorizontalSliderLink();

        logStep("Verify if Horizontal Slider page is opened");
        assertTrue("Unable to load Horizontal Slider page", horizontalSliderPage.isLoaded());

        logStep("Verify if horizontal slider element is visible");
        assertTrue("Horizontal slider is not visible",
                horizontalSliderPage.isElementHorizontalSliderVisible());

        startPosition = horizontalSliderPage.getStartPosition();
        middlePosition = horizontalSliderPage.getMiddlePosition();
        endPosition = horizontalSliderPage.getEndPosition();
    }

    @Test
    public void shouldHorizontalSliderMoveWhenKeyboardArrowButtonsArePressed() {
        BigDecimal position;
        logStep("Move slider to start position: " + startPosition);
        horizontalSliderPage.setSliderPositionTo(startPosition, HorizontalSliderElement.KEYBOARD);
        assertEquals("Fail to set horizontal sliders position", startPosition,
                horizontalSliderPage.getCurrentPosition());

        logStep("Move slider to middle position: " + middlePosition);
        horizontalSliderPage.setSliderPositionTo(middlePosition, HorizontalSliderElement.KEYBOARD);
        assertEquals("Fail to set horizontal sliders position",
                horizontalSliderPage.verifyAndCorrectPositionValue(middlePosition),
                horizontalSliderPage.getCurrentPosition());

        logStep("Move slider to end position: " + endPosition);
        horizontalSliderPage.setSliderPositionTo(endPosition, HorizontalSliderElement.KEYBOARD);
        assertEquals("Fail to set horizontal sliders position", endPosition,
                horizontalSliderPage.getCurrentPosition());

        position = startPosition.subtract(BigDecimal.ONE);
        logStep("Move slider to position before start position: " + position);
        horizontalSliderPage.setSliderPositionTo(position, HorizontalSliderElement.KEYBOARD);
        assertEquals("Fail to set horizontal sliders position", startPosition,
                horizontalSliderPage.getCurrentPosition());

        position = endPosition.add(BigDecimal.ONE);
        logStep("Move slider to position after end position: " + position);
        horizontalSliderPage.setSliderPositionTo(position, HorizontalSliderElement.KEYBOARD);
        assertEquals("Fail to set horizontal sliders position", endPosition,
                horizontalSliderPage.getCurrentPosition());

        position = middlePosition.divide(new BigDecimal(2));
        logStep("Move slider to improperly defined position: " + position);
        horizontalSliderPage.setSliderPositionTo(position, HorizontalSliderElement.KEYBOARD);
        assertEquals("Fail to set horizontal sliders position",
                horizontalSliderPage.verifyAndCorrectPositionValue(position),
                horizontalSliderPage.getCurrentPosition());

        position = new BigDecimal(new BigInteger("233234"), 5);
        logStep("Move slider to improperly defined random position: " + position);
        horizontalSliderPage.setSliderPositionTo(position, HorizontalSliderElement.KEYBOARD);
        assertEquals("Fail to set horizontal sliders position",
                horizontalSliderPage.verifyAndCorrectPositionValue(position),
                horizontalSliderPage.getCurrentPosition());

        logStep("Move slider back to start position: " + startPosition);
        horizontalSliderPage.setSliderPositionTo(startPosition, HorizontalSliderElement.KEYBOARD);
        assertEquals("Fail to set horizontal sliders position", startPosition,
                horizontalSliderPage.getCurrentPosition());
    }

    @Test
    public void shouldHorizontalSliderMoveWhenMouseButtonIsPressedAndMouseIsMoving() {
        BigDecimal position;
        logStep("Move slider to start position: " + startPosition);
        horizontalSliderPage.setSliderPositionTo(startPosition, HorizontalSliderElement.MOUSE);
        assertEquals("Fail to set horizontal sliders position", startPosition,
                horizontalSliderPage.getCurrentPosition());

        logStep("Move slider to middle position: " + middlePosition);
        horizontalSliderPage.setSliderPositionTo(middlePosition, HorizontalSliderElement.MOUSE);
        assertEquals("Fail to set horizontal sliders position",
                horizontalSliderPage.verifyAndCorrectPositionValue(middlePosition),
                horizontalSliderPage.getCurrentPosition());

        logStep("Move slider to end position: " + endPosition);
        horizontalSliderPage.setSliderPositionTo(endPosition, HorizontalSliderElement.MOUSE);
        assertEquals("Fail to set horizontal sliders position", endPosition,
                horizontalSliderPage.getCurrentPosition());

        position = startPosition.subtract(BigDecimal.ONE);
        logStep("Move slider to position before start position: " + position);
        horizontalSliderPage.setSliderPositionTo(position, HorizontalSliderElement.MOUSE);
        assertEquals("Fail to set horizontal sliders position", startPosition,
                horizontalSliderPage.getCurrentPosition());

        position = endPosition.add(BigDecimal.ONE);
        logStep("Move slider to position after end position: " + position);
        horizontalSliderPage.setSliderPositionTo(position, HorizontalSliderElement.MOUSE);
        assertEquals("Fail to set horizontal sliders position", endPosition,
                horizontalSliderPage.getCurrentPosition());

        position = middlePosition.divide(new BigDecimal(2));
        logStep("Move slider to improperly defined position: " + position);
        horizontalSliderPage.setSliderPositionTo(position, HorizontalSliderElement.MOUSE);
        assertEquals("Fail to set horizontal sliders position",
                horizontalSliderPage.verifyAndCorrectPositionValue(position),
                horizontalSliderPage.getCurrentPosition());

        position = new BigDecimal(new BigInteger("212348"), 5);
        logStep("Move slider to improperly defined random position: " + position);
        horizontalSliderPage.setSliderPositionTo(position, HorizontalSliderElement.MOUSE);
        assertEquals("Fail to set horizontal sliders position",
                horizontalSliderPage.verifyAndCorrectPositionValue(position),
                horizontalSliderPage.getCurrentPosition());

        logStep("Move slider back to start position: " + startPosition);
        horizontalSliderPage.setSliderPositionTo(startPosition, HorizontalSliderElement.MOUSE);
        assertEquals("Fail to set horizontal sliders position", startPosition,
                horizontalSliderPage.getCurrentPosition());
    }
}
example54

This example shows how to sort and read data from tables.

After clicking on a column header, the data will be sorted descending and after another click sorted ascending by selected attribute. Watch how both tables' content changes on page DOM. Sorting is performed by JavaScript functions.

example55
Page Class
public class SortableDataTablesPage extends BasePage {

    private static final By selectorTable  = By.cssSelector("table.tablesorter");
    private static final By selectorHeader = By.cssSelector("th");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.SORTABLE_DATA_TABLES.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Data Tables' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.SORTABLE_DATA_TABLES.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Sorts data in given column using ascending order.
     *
     * @param columnNumber The number of column where data should be sorted
     * @param tableNumber  The number of table where data should be sorted
     */
    public void sortColumnAscending(int columnNumber, int tableNumber) {
        WebElement header = this.getTableHeaders(columnNumber, tableNumber);
        String className = header.getAttribute("class");
        if (className.contains("headerSortUp") || !className.contains("headerSortDown")) {
            header.click();
        }
    }

    /**
     * Sorts data in given column using descending order.
     *
     * @param columnNumber The number of the column where data should be sorted
     * @param tableNumber  The number of the table where data should be sorted
     */
    public void sortColumnDescending(int columnNumber, int tableNumber) {
        WebElement header = this.getTableHeaders(columnNumber, tableNumber);
        String className = header.getAttribute("class");
        if (!className.contains("headerSortUp")) {
            header.click();
            if (!className.contains("headerSortDown")) {
                header.click();
            }
        }
    }

    /**
     * Return given column values from chosen table.
     *
     * @param columnNumber The number of the column the data should be retrieved from
     * @param tableNumber  The number of the table the data should be retrieved from
     * @return list of values from given column
     */
    public List<String> getColumnValues(int columnNumber, int tableNumber) {
        WebElement table = getTable(tableNumber);
        return JsoupHelper.findTexts(table, By.cssSelector("tr > td:nth-child(" + (columnNumber + 1)
                + ")"));
    }

    /**
     * Returns column's class name.
     *
     * @param columnNumber The number of the column to get class number from
     * @param tableNumber  The number of the table to get column class name from
     * @return String object representing column's class name
     */
    public String readColumnClass(int columnNumber, int tableNumber) {
        return this.getTableHeaders(columnNumber, tableNumber)
                .getAttribute("class");
    }

    private WebElement getTable(int tableNumber) {
        return new ListElements(selectorTable).getList()
                .get(tableNumber);
    }

    private WebElement getTableHeaders(int columnNumber, int tableNumber) {
        return getTable(tableNumber).findElements(selectorHeader)
                .get(columnNumber);
    }
}
Finding values

Using proper selectors, save elements such as tables and their columns' headers as Web Element Lists. Afterwards, you can get the desired element finding it by index (e. g. table or column number). To get column values, use JsoupHelper and to check if the column is sorted get its class attribute.

Test Class

Before all tests: Open The Internet Main Page

Before each case: Go to Sortable Data Tables Page

Case 1:

  1. Choose a random table

  2. Sort first column "Last Name" in ascending order

  3. Check if column header class contains "headerSortDown"

  4. Save column content to the List

  5. Create List copy and sort it

  6. Compare sorted values and values from the table

Case 2:

  1. Choose a random table

  2. Sort second column "First Name" in descending order

  3. Check if column header class contains "headerSortUp"

  4. Save column content to the List

  5. Create List copy and sort it then reverse it

  6. Compare reversed sorted values and values from the table

@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class SortableDataTablesTest extends TheInternetBaseTest {

    private static SortableDataTablesPage sortableDataTablesPage;

    private List<String> actualValues;
    private List<String> expectedValues;

    @BeforeClass
    public static void setUpBeforeClass() {
        logStep("Open the Url http://the-internet.herokuapp.com/");
        theInternetPage = new TheInternetPage();
        theInternetPage.load();

        logStep("Verify if Url http://the-internet.herokuapp.com/ is opened");
        assertTrue("Unable to load The Internet Page", theInternetPage.isLoaded());
    }

    @Override
    public void setUp() {
        logStep("Click subpage link");
        sortableDataTablesPage = theInternetPage.clickSortableDataTablesLink();

        logStep("Verify if subpage is opened");
        assertTrue("Unable to open Sortable Data Tables page", sortableDataTablesPage.isLoaded());
    }

    @Test
    public void shouldLastNameColumnBeOrderedAscendingAfterSort() {
        int columnNumber = 0;
        int tableNumber = new Random().nextInt(2);

        logStep("Sort 'Last Name' column");
        sortableDataTablesPage.sortColumnAscending(columnNumber, tableNumber);
        assertTrue("Unable to set ascending order for 'Last Name' column",
                sortableDataTablesPage.readColumnClass(columnNumber, tableNumber)
                        .contains("headerSortDown"));

        logStep("Verify data order for 'Last Name' column");
        actualValues = sortableDataTablesPage.getColumnValues(columnNumber, tableNumber);
        expectedValues = new ArrayList<String>(actualValues);
        Collections.sort(expectedValues);
        assertEquals("'Last Name' column is not sorted in ascending order",
                expectedValues, actualValues);
    }

    @Test
    public void shouldFirstNameColumnBeOrderedDescendingAfterSort() {
        int columnNumber = 1;
        int tableNumber = new Random().nextInt(2);

        logStep("Sort 'First Name' column");
        sortableDataTablesPage.sortColumnDescending(columnNumber, tableNumber);
        assertTrue("Unable to set descending order for 'First Name' column",
                sortableDataTablesPage.readColumnClass(columnNumber, tableNumber)
                        .contains("headerSortUp"));

        logStep("Verify data order for 'First Name' column");
        actualValues = sortableDataTablesPage.getColumnValues(columnNumber, tableNumber);
        expectedValues = new ArrayList<String>(actualValues);
        Collections.sort(expectedValues);
        Collections.reverse(expectedValues);
        assertEquals("'First Name' column is not sorted in descending order",
                expectedValues, actualValues);
    }
}
example56

This example shows how to process HTTP status codes returned by page

When you click status code link, you will be redirected to the subpage which returns the proper HTTP status code. In order to check what code was returned:

  1. Open developer tools

  2. Go to Network tab

  3. Click request name

  4. Find a code number in Headers section

example57
Page Class

Add new methods to existing Status Codes Home Page Class

public class StatusCodesHomePage extends BasePage {

    private static final By selectorLink200Code = By.linkText("200");
    private static final By selectorLink301Code = By.linkText("301");
    private static final By selectorLink404Code = By.linkText("404");
    private static final By selectorLink500Code = By.linkText("500");

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.STATUS_CODES.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Status Codes' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.STATUS_CODES.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    /**
     * Verifies if given link is displayed.
     *
     * @param selector Selector of the given link
     * @return true if link is displayed
     */
    public boolean isLinkCodeDisplayed(By selector) {
        return getDriver().findElementDynamic(selector)
                .isDisplayed();

    }

    /**
     * Clicks '200' link.
     *
     * @return StatusCodesCodePage object
     */
    public StatusCodesCodePage clickCode200Link() {
        return clickCodeLink(selectorLink200Code);
    }

    /**
     * Clicks '301' link.
     *
     * @return StatusCodesCodePage object
     */
    public StatusCodesCodePage clickCode301Link() {
        return clickCodeLink(selectorLink301Code);
    }

    /**
     * Clicks '404' link.
     *
     * @return StatusCodesCodePage object
     */
    public StatusCodesCodePage clickCode404Link() {
        return clickCodeLink(selectorLink404Code);
    }

    /**
     * Clicks '500' link.
     *
     * @return StatusCodesCodePage object
     */
    public StatusCodesCodePage clickCode500Link() {
        return clickCodeLink(selectorLink500Code);
    }

    /**
     * Clicks code link according to given code number.
     *
     * @param code Given code
     * @return StatusCodesCodePage object
     */
    public StatusCodesCodePage clickCodeLink(String code) {
        return clickCodeLink(By.linkText(code));
    }

    private StatusCodesCodePage clickCodeLink(By selector) {
        String codeNumber = getCodeNumberToCheck(selector);
        getDriver().findElementDynamic(selector)
                .click();
        return new StatusCodesCodePage(codeNumber);
    }

    private String getCodeNumberToCheck(By selector) {
        return getDriver().findElementDynamic(selector)
                .getText();
    }
}

Create a page class for status codes subpages as well. In the class constructor specify which code number should be returned.

public class StatusCodesCodePage extends BasePage {

    private static final By selectorDisplayedText   = By.cssSelector("#content > div > p");
    private static final By selectorLinkToCodesPage = By.cssSelector("#content > div > p > a");

    private String codeNumber;

    public StatusCodesCodePage(String codeNumber) {
        this.codeNumber = codeNumber;
    }

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded();
        return getDriver().getCurrentUrl()
                .contains(PageSubURLsProjectYEnum.STATUS_CODES.getValue() + '/');
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'Status Codes' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.STATUS_CODES.getValue() + '/' + codeNumber);
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }

    public String getCodeNumber() {
        return codeNumber;
    }

    /**
     * Verifies if page is loaded with given code number.
     *
     * @param codeNumber Expected code number
     * @return true if expected code number is loaded with web page
     */
    public boolean isLoadedWithStatusCode(String codeNumber) {
        return getDriver().getCurrentUrl()
                .equals(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue() +
                PageSubURLsProjectYEnum.STATUS_CODES.getValue() + "/" + codeNumber);
    }

    /**
     * Returns displayed code number.
     * <p>
     * Code number is retrieved from following text displayed on the page:<b>
     * 'This page returned a *** status code.', where *** represent the code number to be
     * returned.
     * </p>
     *
     * @return String object representing the displayed code number retrieved from specific sentence.
     */
    public String getDisplayedCodeNumber() {
        return getDriver().findElementDynamic(selectorDisplayedText)
                .getText()
                .substring(21, 24);
    }

    /**
     * Clicks link to return to 'Code Page'.
     *
     * @return StatusCodesHomePage object
     */
    public StatusCodesHomePage clickLinkToCodePage() {
        getDriver().findElementDynamic(selectorLinkToCodesPage)
                .click();
        return new StatusCodesHomePage();
    }
}
Test Class

Before all tests: Open The Internet Main Page, go to Status Codes page

Steps:

For each status code

  1. Click code link

  2. Check if the page is loaded with an expected code number

  3. Check if the displayed code number equals the expected number

  4. Go back to Status Codes Home Page

@Category({ TestsSelenium.class, TestsChrome.class, TestsFirefox.class, TestsIE.class })
public class StatusCodeTest extends TheInternetBaseTest {

    private static StatusCodesHomePage statusCodesHomePage;
    private        StatusCodesCodePage statusCodesCodePage;

    private String[] codes = { "200", "301", "404", "500" };

    @BeforeClass
    public static void setUpBeforeClass() {
        statusCodesHomePage = shouldTheInternetPageBeOpened().clickStatusCodesLink();

        logStep("Verify if Status Codes Home page is opened");
        assertTrue("Unable to open Status Codes Home page", statusCodesHomePage.isLoaded());
    }

    @Test
    public void shouldProperCodeBeDisplayedAfterClickCodeLink() {

        for (String code : codes) {
            logStep("Click link to " + code + " code");
            statusCodesCodePage = statusCodesHomePage.clickCodeLink(code);

            logStep("Verify if proper web page corresponding to the code is opened");
            assertTrue("Unable to open proper web page",
                    statusCodesCodePage.isLoadedWithStatusCode(code));

            logStep("Verify if the displayed code is equal to the expected one");
            assertEquals(code, statusCodesCodePage.getDisplayedCodeNumber());

            logStep("Click link to come back to 'Status Codes' page");
            statusCodesCodePage.clickLinkToCodePage();
        }
    }
}
First Steps
Page Object

Your Product Under Test will be the following website: http://the-internet.herokuapp.com/

At first, create an Object to represent The Internet Main Page:

public class TheInternetPage extends BasePage

Each class which extends BasePage class must override three methods:

  • public boolean isLoaded() - returns true if the page is loaded and false if not

  • public void load() - loads the page

  • public String pageTitle() - returns page title

public class TheInternetPage extends BasePage {

    @Override
    public boolean isLoaded() {
        BFLogger.logDebug("The internet page is loaded: " + getDriver().getCurrentUrl());
        return getDriver().getCurrentUrl()
                .equals(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue());
    }

    @Override
    public void load() {
        BFLogger.logDebug("Load 'The internet' page.");
        getDriver().get(GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue());
        getDriver().waitForPageLoaded();
    }

    @Override
    public String pageTitle() {
        return getActualPageTitle();
    }
}
Environment Variables

In Page classes, when you load/start web, it is uncommon to save fixed main URL.

Instead of hardcoded main URL variable, you build your Page class with a dynamic variable.

How to create / update system environment

Dynamic variable values are stored under path \src\resources\enviroments\environments.csv.

image1

By default, the environment takes value from DEV column.

Access to the external file variables

Create a class GetEnvironmentParam to map values from an external file with Page class:

public enum GetEnvironmentParam {

    // Name if enum must be in line with cell name in /src/resources/environments/environment.csv
    WWW_FONT_URL,
    TOOLS_QA,
    WEB_SERVICE,
    THE_INTERNET_MAIN_PAGE,
    ELEMENTAL_SELENIUM_PAGE;

    public String getValue() {

        if (null == BaseTest.getEnvironmentService()) {
            throw new BFInputDataException("Environment Parameters class wasn't initialized properly");
        }

        return BaseTest.getEnvironmentService()
                .getValue(this.name());

    }

    @Override
    public String toString() {

        return this.getValue();

    }
}

When you add a new row to environments.csv also add a new variable to GetEnvironmentParam class.

In Page class access environmental variable using this method:

GetEnvironmentParam.THE_INTERNET_MAIN_PAGE.getValue();
Selectors
Create selectors

Create a selector for every interactable element on a webpage using By type. Find elements and it’s attributes using browser developer mode (F12).

image2
private static final By abTestLinkSelector               = By.cssSelector("li >
            a[href*='abtest']");
    private static final By basicAuthLinkSelector            = By.cssSelector("li >
            a[href*='basic_auth']");
    private static final By brokenImageLinkSelector          = By.cssSelector("li >
            a[href*='broken_images']");
    private static final By challengingDomLinkSelector       = By.cssSelector("li >
            a[href*='challenging_dom']");
    private static final By checkboxesLinkSelector           = By.cssSelector("li >
            a[href*='checkboxes']");
    private static final By contextMenuLinkSelector          = By.cssSelector("li >
            a[href*='context_menu']");
    private static final By disappearingElementsLinkSelector = By.cssSelector("li >
            a[href*='disappearing_elements']");
    private static final By dragAndDropLinkSelector          = By.cssSelector("li >
            a[href*='drag_and_drop']");
    private static final By dropdownLinkSelector             = By.cssSelector("li >
            a[href*='dropdown']");
    private static final By dynamicContentLinkSelector       = By.cssSelector("li >
            a[href*='dynamic_content']");
    private static final By dynamicControlsLinkSelector      = By.cssSelector("li >
            a[href*='dynamic_controls']");
    private static final By dynamicLoadingLinkSelector       = By.cssSelector("li >
            a[href*='dynamic_loading']");
    private static final By exitIntentLinkSelector           = By.cssSelector("li >
            a[href*='exit_intent']");
    private static final By fileDownloadLinkSelector         = By.cssSelector("li >
            a[href$='download']");
    private static final By fileUploadLinkSelector           = By.cssSelector("li >
           a[href*='upload']");
    private static final By floatingMenuLinkSelector         = By.cssSelector("li >
           a[href*='floating_menu']");
    private static final By forgotPasswordLinkSelector       = By.cssSelector("li >
           a[href*='forgot_password']");
    private static final By formAuthenticationLinkSelector   = By.cssSelector("li >
           a[href*='login']");
    private static final By framesLinkSelector               = By.cssSelector("li >
           a[href*='frames']");
    private static final By geolocationLinkSelector          = By.cssSelector("li >
           a[href*='geolocation']");
    private static final By horizontalSliderLinkSelector     = By.cssSelector("li >
           a[href*='horizontal_slider']");
    private static final By hoversLinkSelector               = By.cssSelector("li >
           a[href*='hovers']");
    private static final By infiniteScrollLinkSelector       = By.cssSelector("li >
           a[href*='infinite_scroll']");
    private static final By javaScriptAlertLinkSelector      = By.cssSelector("li >
           a[href*='javascript_alerts']");
    private static final By javaScriptErrorLinkSelector      = By.cssSelector("li >
           a[href*='javascript_error']");
    private static final By jQueryUIMenuLinkSelector         = By.cssSelector("li >
           a[href*='jqueryui/menu']");
    private static final By keyPressesLinkSelector           = By.cssSelector("li >
           a[href*='key_presses']");
    private static final By largeAndDeepDOMLinkSelector      = By.cssSelector("li >
           a[href*='large']");
    private static final By multipleWindowsLinkSelector      = By.cssSelector("li >
           a[href*='windows']");
    private static final By nestedFramesLinkSelector         = By.cssSelector("li >
           a[href*='nested_frames']");
    private static final By notificationMessagesLinkSelector = By.cssSelector("li >
           a[href*='notification_message']");
    private static final By redirectLinkSelector             = By.cssSelector("li >
           a[href*='redirector']");
    private static final By secureFileDownloadLinkSelector   = By.cssSelector("li >
           a[href*='download_secure']");
    private static final By shiftingContentLinkSelector      = By.cssSelector("li >
           a[href*='shifting_content']");
    private static final By slowResourcesLinkSelector        = By.cssSelector("li >
           a[href*='slow']");
    private static final By sortableDataTablesLinkSelector   = By.cssSelector("li >
           a[href*='tables']");
    private static final By statusCodesLinkSelector          = By.cssSelector("li >
           a[href*='status_codes']");
    private static final By typosLinkSelector                = By.cssSelector("li >
           a[href*='typos']");
    private static final By wYSIWYGEditorLinkSelector        = By.cssSelector("li >
           a[href*='tinymce']");
Implement methods

Then use these selectors to create Objects and perform actions on page elements:

public ABtestPage clickABtestingLink() {
        new Button(abTestLinkSelector).click();
        return new ABtestPage();
    }

    public BasicAuthPage clickBasicAuthLink() {
        getDriver().waitForPageLoaded();
        WebElement link = getDriver().findElementDynamic(basicAuthLinkSelector);
        JavascriptExecutor executor = (JavascriptExecutor) getDriver();
        executor.executeScript("var elem=arguments[0]; setTimeout(function() {elem.click();}, 100)",
                link);
        return new BasicAuthPage();
    }

    public BrokenImagePage clickBrokenImageLink() {
        new Button(brokenImageLinkSelector).click();
        return new BrokenImagePage();
    }

    public ChallengingDomPage clickChallengingDomLink() {
        new Button(challengingDomLinkSelector).click();
        return new ChallengingDomPage();
    }

    public CheckboxesPage clickCheckboxesLink() {
        new Button(checkboxesLinkSelector).click();
        return new CheckboxesPage();
    }

    public ContextMenuPage clickContextMenuLink() {
        new Button(contextMenuLinkSelector).click();
        return new ContextMenuPage();
    }

    public DisappearingElementsPage clickDisappearingElementsLink() {
        new Button(disappearingElementsLinkSelector).click();
        return new DisappearingElementsPage();
    }

    public DragAndDropPage clickDragAndDropLink() {
        new Button(dragAndDropLinkSelector).click();
        return new DragAndDropPage();
    }

    public DropdownPage clickDropdownLink() {
        new Button(dropdownLinkSelector).click();
        return new DropdownPage();
    }

    public DynamicContentPage clickDynamicContentLink() {
        new Button(dynamicContentLinkSelector).click();
        return new DynamicContentPage();
    }

    public DynamicControlsPage clickDynamicControlsLink() {
        new Button(dynamicControlsLinkSelector).click();
        return new DynamicControlsPage();
    }

    public DynamicLoadingPage clickDynamicLoadingLink() {
        new Button(dynamicLoadingLinkSelector).click();
        return new DynamicLoadingPage();
    }

    public ExitIntentPage clickExitIntentLink() {
        new Button(exitIntentLinkSelector).click();
        return new ExitIntentPage();
    }

    public FileDownloadPage clickFileDownloadLink() {
        new Button(fileDownloadLinkSelector).click();
        return new FileDownloadPage();
    }

    public FileUploadPage clickFileUploadLink() {
        new Button(fileUploadLinkSelector).click();
        return new FileUploadPage();
    }

    public FloatingMenuPage clickFloatingMenuLink() {
        new Button(floatingMenuLinkSelector).click();
        return new FloatingMenuPage();
    }

    public ForgotPasswordPage clickForgotPasswordLink() {
        new Button(forgotPasswordLinkSelector).click();
        return new ForgotPasswordPage();
    }

    public FormAuthenticationPage clickFormAuthenticationLink() {
        new Button(formAuthenticationLinkSelector).click();
        return new FormAuthenticationPage();
    }

    public FramesPage clickFramesLink() {
        new Button(framesLinkSelector).click();
        return new FramesPage();
    }

    public GeolocationPage clickGeolocationLink() {
        new Button(geolocationLinkSelector).click();
        return new GeolocationPage();
    }

    public HorizontalSliderPage clickHorizontalSliderLink() {
        new Button(horizontalSliderLinkSelector).click();
        return new HorizontalSliderPage();
    }

    public HoversPage clickHoversLink() {
        new Button(hoversLinkSelector).click();
        return new HoversPage();
    }

    public InfiniteScrollPage clickInfiniteScrollLink() {
        new Button(infiniteScrollLinkSelector).click();
        return new InfiniteScrollPage();
    }

    public JavaScriptAlertsPage clickJavaScriptAlertLink() {
        new Button(javaScriptAlertLinkSelector).click();
        return new JavaScriptAlertsPage();
    }

    public JavaScriptErrorPage clickJavaScriptErrorLink() {
        new Button(javaScriptErrorLinkSelector).click();
        return new JavaScriptErrorPage();
    }

    public JQueryUIMenuPage clickJQueryUIMenuLink() {
        new Button(jQueryUIMenuLinkSelector).click();
        return new JQueryUIMenuPage();
    }

    public KeyPressesPage clickKeyPressesLink() {
        new Button(keyPressesLinkSelector).click();
        return new KeyPressesPage();
    }

    public LargeAndDeepDOMPage clickLargeAndDeepDOMLink() {
        new Button(largeAndDeepDOMLinkSelector).click();
        return new LargeAndDeepDOMPage();
    }

    public MultipleWindowsPage clickmultipleWindowsLink() {
        new Button(multipleWindowsLinkSelector).click();
        return new MultipleWindowsPage();
    }

    public NestedFramesPage clickNestedFramesLink() {
        new Button(nestedFramesLinkSelector).click();
        return new NestedFramesPage();
    }

    public NotificationMessagesPage clickNotificationMessagesLink() {
        new Button(notificationMessagesLinkSelector).click();
        return new NotificationMessagesPage();
    }

    public RedirectLinkPage clickRedirectLink() {
        new Button(redirectLinkSelector).click();
        return new RedirectLinkPage();
    }

    public SecureFileDownloadPage clickSecureFileDownloadLink() {
        new Button(secureFileDownloadLinkSelector).click();
        return new SecureFileDownloadPage();
    }

    public ShiftingContentPage clickShiftingContentLink() {
        new Button(shiftingContentLinkSelector).click();
        return new ShiftingContentPage();
    }

    public SlowResourcesPage clickSlowResourcesLink() {
        new Button(slowResourcesLinkSelector).click();
        return new SlowResourcesPage();
    }

    public SortableDataTablesPage clickSortableDataTablesLink() {
        new Button(sortableDataTablesLinkSelector).click();
        return new SortableDataTablesPage();
    }

    public StatusCodesHomePage clickStatusCodesLink() {
        new Button(statusCodesLinkSelector).click();
        return new StatusCodesHomePage();
    }

    public TyposPage clickTyposLink() {
        new Button(typosLinkSelector).click();
        return new TyposPage();
    }

    public WYSIWYGEditorPage clickWYSIWYGEditorLink() {
        new Button(wYSIWYGEditorLinkSelector).click();
        return new WYSIWYGEditorPage();
    }

These methods create a Button object for every link on The Internet Page and click it to redirect on a different subpage.

Elements types

MrChecker includes Object types for various elements existing on webpages such as Button, TextBox etc. There is also WebElement class and getDriver().findElementDynamic(By selector) method for creating webpage objects dynamically and performing basic actions:

Instead of using static types you can use:

    public TyposPage clickTyposLink() {
        WebElement checkboxesLink = getDriver().findElementDynamic(checkboxesLinkSelector);
        checkboxesLink.click();
        return new TyposPage();
    }

Or perform actions without creating a variable:

    public TyposPage clickTyposLink() {
        getDriver().findElementDynamic(checkboxesLinkSelector).click();
        return new TyposPage();
    }
The Internet Base Test
Test Class

Create Test class and override methods:

  • public void setUp() - executes before each test

  • public void tearDown() - executes after each test

public class TheInternetBaseTest extends BaseTest {
    @Override
    public void setUp() {

    }

    @Override
    public void tearDown() {
        logStep("Navigate back to The-Internet page");
        BasePage.navigateBack();
    }
}

logStep(String message) method doesn’t exist yet so you should create it:

    protected static int             step = 0;

     /**
     * Logs test step including step number calculated individually for each test.
     *
     * @param message Text message representing step description.
     */
    public static void logStep(String message) {
        BFLogger.logInfo("Step " + ++step + ": " + message);
    }

Write a method for loading The Internet Page and checking if it is properly opened:

    protected static TheInternetPage theInternetPage;

    /**
     * Performs operations required for verifying if The Internet Page is properly opened.
     *
     * @return TheInternetPage
     */
    public static TheInternetPage shouldTheInternetPageBeOpened() {

        logStep("Open the Url http://the-internet.herokuapp.com/");
        theInternetPage = new TheInternetPage();
        theInternetPage.load();

        logStep("Verify if Url http://the-internet.herokuapp.com/ is opened");
        assertTrue("Unable to load The Internet Page", theInternetPage.isLoaded());

        return theInternetPage;
    }

This Test class can’t be launched because it doesn’t contain any @Test methods. It’s been created only for supporting other Test classes.

BFLogger

BFLogger is a default MrChecker logging tool. Use it to communicate important information from test execution. There are three basic logging methods:

  • logInfo(String message) - used for test steps

  • logDebug(String message) - used for non-official information, either during the test build process or in Page Object files

  • logError(String message) - used to emphasize critical information

Logs will be visible in the console and in the log file under path: MrChecker_Test_Framework\workspace\project-folder\logs

E2E Tutorials

MrChecker E2E tutorials

In order to learn more about MrChecker structure, start from Project Organisation section and then check out our fantastic tutorials:

How to create a basic test in MrChecker
Example: Booking a table

As an example to test we will use MyThaiStar booking page.
In order to book a table, do the following steps:

  1. Open MyThaiStar Book Table Page

  2. Enter booking data: Date and time, Name, Email and number of Table guests

  3. Click Accept terms

  4. Click Book table

  5. Display confirmation box and send booking

  6. Check if the booking was successful.

image1
image2

You can go through these steps manually and doublecheck the result.

How to prepare a test
1. Create BookTablePage class

You will need a class which will represent MyThaiStart booking page.
Fill the required methods with the following code:

public class BookTablePage extends BasePage {

    @Override
    public boolean isLoaded() {
        getDriver().waitForPageLoaded(); //waits untli the page is loaded
        return getDriver().getCurrentUrl()
                .equals("https://mts-devonfw-core.cloud.okteto.net/bookTable"); //checks if current page address equals MyThaiStar booking page adress
    }

    @Override
    public void load() {
        getDriver().get("https://mts-devonfw-core.cloud.okteto.net/bookTable"); //loads page under specified adress
        getDriver().waitForPageLoaded(); //waits until the page is loaded
    }

    @Override
    public String pageTitle() {
        return "My Thai Star"; //returns page title
    }
}

getDriver() method allows accessing Selenium Web Driver which performs actions on the webpage.

As this page class represents the MyThaiStar booking page, you have to set up selectors for web elements required in the test case. In the example you have to create selectors for elements we’ll interact with:

  • Date and time input field

  • Name input field

  • Email input field

  • Table guests input field

  • Accept terms checkbox

  • Book table button

Selectors will be implemented as fields.

Example of the selector for Date and time input field:

/** Date field search criteria */
private static final By dateSearch = By.cssSelector("input[formcontrolname='bookingDate']");

The input field’s name "bookingDate" was found by using the developer console in Google Chrome. How to prepare an everlasting selector?

image3

This selector can be used to create a WebElement object of the said input field. Therefore, you will create a new method and call it "enterTimeAndDate".

public void enterTimeAndDate(String date) {
    WebElement dateInput = getDriver().findElementDynamic(dateSearch); //creates a new WebElement to access Date and time input field
    dateInput.sendKeys(date); //enters date value
}

Now you can create other selectors and objects and methods for every element on the webpage:

/** Name input field search criteria */
private static final By nameSearch = By.cssSelector("input[formcontrolname='name']");

/** Email input field search criteria */
private static final By emailSearch = By.cssSelector("input[formcontrolname='email']");

/** Number of guests search criteria */
private static final By guestsSearch = By.cssSelector("input[formcontrolname='assistants']");

/** Check box search criteria */
private static final By checkboxSearch = By.cssSelector("mat-checkbox[data-name='bookTableTerms']");

/** Book table button search criteria */
private static By bookTableSearch = By.name("bookTableSubmit");
public void enterName(String name) {
    WebElement nameInput = getDriver().findElementDynamic(nameSearch); //creates a new WebElement to access name input field
    nameInput.sendKeys(name); //enters name value
}

public void enterEmail(String email) {
    WebElement emailInput = getDriver().findElementDynamic(emailSearch); //creates a new WebElement to access email input field
    emailInput.sendKeys(email); //enters email value
}

public void enterGuests(int amountOfGuests) {
    WebElement guestsInput = getDriver().findElementDynamic(guestsSearch); //creates a new WebElement to access amount of guests input field
    guestsInput.sendKeys(Integer.toString(amountOfGuests)); //enters the number of guests value converted from integer to string
}

public void acceptTerms() {
    WebElement checkbox = getDriver().findElementDynamic(checkboxSearch); //creates aa new WebElement to access accept terms checkbox
    WebElement square = checkbox.findElement(By.className("mat-checkbox-inner-container")); //creates a new WebElement to access inner square
    JavascriptExecutor js = (JavascriptExecutor) getDriver(); //creates a Javascript executor object
    js.executeScript("arguments[0].click()", square); //executes a script which clicks the square

}

public void clickBookTable() {
    WebElement buttonbutton = getDriver().findElementDynamic(bookTableSearch); //creates a new WebElement to access book table button
    getDriver().waitUntilElementIsClickable(bookTableSearch); //waits until a button might be clicked
    buttonbutton.click(); //clicks the button
}

You can use those methods in order to create a new method to go through the whole booking process:

public ConfirmBookPage enterBookingData(String date, String name, String email, int guests) {
    enterTimeAndDate(date);
    enterName(name);
    enterEmail(email);
    enterGuests(guests);
    acceptTerms();

    clickBookTable();

    return new ConfirmBookPage();
}
2. Create ConfirmBookPage class

As you can see, this method returns another page object that has not yet been created. This step is required, as the booking information that you would like to check is on another webpage. This means that you will have to create another page class and call it ConfirmBookPage:

public class ConfirmBookPage extends BasePage {

    /** Confirmation dialog search criteria */
    private static final By confirmationDialogSearch = By.className("mat-dialog-container");

    /** Send confirmation button search criteria */
    private static final By sendButtonSearch = By.name("bookTableConfirm");

    /** Cancel confirmation button search criteria */
    private static final By cancelButtonSearch = By.name("bookTableCancel");

    @Override
    public boolean isLoaded() {
        //creates a new WebElement to access confirmation dialog box
        WebElement confirmationDialog = getDriver().findElementDynamic(confirmationDialogSearch);

        return confirmationDialog.isDisplayed(); //checks if the box is displayed
    }

    //this method won't be called because the page is loaded only after clicking book table button
    @Override
    public void load() {
        BFLogger.logError("MyThaiStar booking confirmation page was not loaded."); //logs error
    }

    @Override
    public String pageTitle() {
        return "My Thai Star";
    }

    public void confirmBookingData() {
        WebElement sendButton = getDriver().findElementDynamic(sendButtonSearch); //creates a new WebElement to access confirmation button
        sendButton.click(); //clicks the send button
    }

    public void cancelBookingData() {
        WebElement cancelButton = getDriver().findElementDynamic(cancelButtonSearch); //creates a new WebElement to access resignation button
        cancelButton.click(); //clicks the cancel button
    }
}
image4

After the click on Send button - the green confirmation dialogue appears with the message "Table successfully booked":

image5

To be able to check if the booking was successful, you should go back to the BookTablePage class and add one more method in order to check if the green box was displayed:

/** Dialog search criteria */
private static final By dialogSearch = By.className("bgc-green-600");

public boolean checkConfirmationDialog() {
    WebElement greenConfirmationDialog = getDriver().findElementDynamic(dialogSearch); //creates a new WebElement to access confirmation dialog

    return greenConfirmationDialog.isDisplayed(); //checks if the dialog is displayed
}
3. Create BookTableTest class

At this point you can start creating a test class:

import static org.junit.Assert.assertTrue;

public class BookTableTest extends BaseTest {
    private static BookTablePage bookTablePage = new BookTablePage(); //the field contains book table page object

    @BeforeClass
    public static void setUpBeforeClass() {
        bookTablePage.load(); //loads book table page
    }

    @AfterClass
    public static void tearDownAfterClass() {

    }

    @Override
    public void setUp() {
        if (!bookTablePage.isLoaded()) {
            bookTablePage.load(); //if the page is not loaded, loads it
        }
    }

    @Override
    public void tearDown() {

    }
}
4. Write the first test

You can prepare our first test method using the methods from page classes

@Test
public void Test_BookTableAndCheckConfirmation() {
    String date = "07/23/2019 1:00 PM"; //replace with tommorow's date in format "MM/dd/yyyy hh:mm a"
    String name = "Smith"; //name field
    String email = "smith@somemail.com"; //email field
    int guests = 3; //number of guests

    //enters booking data and returns a new confirmation page
    ConfirmBookPage confirmBookPage = bookTablePage.enterBookingData(date, name, email, guests);
    confirmBookPage.confirmBookingData(); //confirms booking

    //checks if the green dialog box appears, if it does, test is passed, if not, the test failed and displays message given in the first argument
    assertTrue("Test failed: Table not booked", bookTablePage.checkConfirmationDialog()); //returns true if dialog box appears and false if not
}
5. Run the test

Run the test by right-clicking on the test method → Run as → JUnit test.

image6
Last updated 2022-08-02 10:22:21 UTC