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:
Enter the project path and select projects to import.
When the import is finished, update the project structure - ALT + F5
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:
Create a new folder for the project and enter its path. Select project and files to export:
Change project name and other properties, if necessary, in pom.xml file:
Then you can import the project to the workspace and create new packages and classes.
Creating new packages
-
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:
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
The goal of this test is to open A/B Test subpage and redirect to another website.
Steps:
-
Open The Internet Main Page
-
Click A/B Testing link and go to A/B Test subpage
-
Click Elemental Selenium link and open it in new tab
-
Switch to Elemental Selenium page and check if it’s loaded
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(); } }
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()
In this test case you need selector for only one page element:
private static final By elementalSeleniumLinkSelector = By.cssSelector("div > div > a");
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)); }
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(); } }
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()); } }
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.
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.
In this test case, the goal is to pass username and password authorization and login to the next page.
Steps:
-
Open The Internet Main Page
-
Click on Basic Auth link
-
Open pop-up login window
-
Enter valid username and password
-
Open next subpage and verify if the user logged in successfully.
Create a page class which represents Basic Auth subpage after proper login.
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); }
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'.
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.
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 .
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.
Steps:
-
Open The Internet Main Page
-
Click Broken Image link and go to Broken Image subpage
-
Get the 3 images' dimensions and compare them with expected values
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(); } }
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.
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 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
Steps:
-
Open The Internet Main Page
-
Click Challenging DOM link and go to Challenging DOM subpage
-
Get and save table values
-
Click the first button
-
Get table values again
-
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.
A checkbox is a simple web element which can be selected or unselected by clicking on it.
Steps:
-
Open The Internet Main Page
-
Click Checkboxes link and go to Checkboxes page
-
Test if the first checkbox is unchecked
-
Select the first checkbox
-
Test if the first checkbox is checked
-
Test if the second checkbox is checked
-
Unselect second checkbox
-
Test if the second checkbox is unchecked
Because both checkboxes are in one form, it’s possible to locate them by one selector and then access each individual one by index.
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 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.
@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.
After refreshing page (F5) a few times, a new element should appear:
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.
Steps:
-
Load The Internet Main Page
-
Click Disappearing Elements link and go to that subpage
-
Check if Menu Buttons exist on the page
-
Refresh the page until a new element appears
-
Check if Gallery Button exists
-
Check if the number of buttons equals the expected value
-
Refresh the page until an element disappears
-
Check if Gallery Button does not exist
-
Check if the number of buttons is smaller than before
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.
@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.
The page can easily be broken. You can try to do so and check how the page structure changed in browser developer mode.
Steps:
-
Open The Internet Main Page
-
Click Drag and Drop link and open subpage
-
Check if the Drag and Drop message is visible
-
Check if element A is in container A and B in container B
-
Move element A to position B
-
Check if element A is in container B and B in container A
-
Move element B to position A
-
Again check if element A is in container A and B in container B
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);
@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.
Check in the developer mode how a Dropdown List’s content has been organized.
Notice that the Dropdown Options have different attributes, such as "disabled" or "selected".
Steps:
-
Open The Internet Main Page
-
Click the Dropdown link and go to the subpage
-
Select first dropdown Option
-
Check if Option 1 is selected
-
Select second dropdown Option
-
Check if Option 2 is selected
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 is MrChecker’s class, which contains methods for performing the dropdown list of actions:
elementDropdownList() - returns DropdownListElement Object
@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.
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.
Steps:
-
Open The Internet Main Page
-
Click Dynamic Content link and load subpage
-
Save page images sources and descriptions before the refresh
-
Refresh page
-
Save page images sources and it’s descriptions after refresh
-
Compare page content before and after refresh and verify if it’s different
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 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.
@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.
Go to Example 1:
Click "start" and see what happens:
When loading ends, you should see the following message:
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:
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:
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.
After clicking "Start", the element with the loading bar is been created.
After a certain time, the loading bar becomes invisible, and then the script creates "Hello World!" element and displays it.
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(); } }
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; } });
Case 1 steps:
-
Open The Internet Main Page
-
Click Dynamic Loading link and go to a subpage with examples
-
Check if the page is loaded and "Dynamically Loaded Page Elements" header is visible
-
Click Example 1 link and load site
-
Verify if the "Start" button is visible
-
Click "Start"
-
Wait for the loading bar to disappear and check if the displayed message is as it should be
-
Go back to Dynamic Loading page
Case 2 steps:
-
Check if the page is loaded and "Dynamically Loaded Page Elements" header is visible
-
Click Example 2 link and load site
-
Verify if the "Start" button is visible
-
Click "Start"
-
Wait for the loading bar to disappear
-
Wait for the message to appear and check if it is as it should be
-
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.
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:
Check in the browser’s developer mode if this window exists in Page DOM
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".
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(); } } }
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 class can perform mouse movement. Method mouseMove(int x, int y)
moves the remote mouse to given coordinates.
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.
Steps:
-
Open The Internet Main Page
-
Click Exit Intent link and load subpage
-
Check if the page is loaded and "Exit Intent" message is visible
-
Verify if Modal Window is hidden
-
Move mouse out of the viewport
-
Check if Modal Window is visible
-
Verify if Modal Window title is correct
-
Click 'close' button
-
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.
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:
-
Open The Internet Main Page
-
Click on the File Download link and open subpage
-
Click on "some-file.txt" download link and download file
-
Check if the file exists in the appropriate folder
-
Delete the file
-
Check if the file doesn’t exist in the folder
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.
@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()); } }
This case shows how to pass through the standard authentication page.
When you enter the correct credentials, you should see the next page:
If user data is wrong, an appropriate message appears:
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(); } }
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
-
String
getText()
method returns visible text from label
Prepare six test cases:
-
Try to login with empty user data and check if the error message appears
-
Try to login with empty username and valid password and check if the error message appears
-
Try to login with a valid username and empty password and check if the error message appears
-
Try to login with invalid username and invalid password and check if the error message appears
-
Try to login with a valid username and valid password and check if success login message appears, then log out
-
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.
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.
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.
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 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.
Steps:
-
Open The Internet Main Page
-
Go to Hovers page
-
Move mouse over random image
-
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.
This case shows how to test pop-up JS alerts.
After clicking one of the buttons, an adequate alert should appear.
Performed action will be displayed under "Result" label.
In developer mode, you can view JavaScript which creates alerts.
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); } }
Using switchTo()
method you can change processed content. switchTo().alert()
allows performing actions on appearing alerts such as accepting, dismissing or entering keys.
Before all tests: Open The Internet Main Page and go to JavaScript Alert page
-
Click JS Alert button, accept alert and check if Result message returns performed an action
-
Click JS Confirm button, accept alert and check if Result message returns performed action
-
Click JS Confirm button, dismiss alert and check if Result message returns performed action
-
Click JS Prompt button, write random text, accept alert and check if Result message returns performed action with written text
-
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(); } }
This simple case shows how to test key pressing
This site uses JavaScript to read the key pressed and display its value.
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(); } }
Steps:
-
Open The Internet Main Page
-
Go to Key Presses site
-
Press a key
-
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()); } }
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.
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(); } }
Steps:
-
Open The Internet Main Page
-
Go to Multiple Windows Page
-
Click the link
-
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()); } }
This simple case shows how to approach redirecting links.
After clicking on the link, you will be redirected to Status Codes 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(); } }
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(); } }
Steps:
-
Open The Internet Main Page
-
Go to Redirection Page
-
Click the link
-
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()); } }
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.
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); } }
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
Before all tests: Open The Internet Main Page
Before each case:
-
Go to Horizontal Slider Page
-
Check if the slider is visible
-
Save start, middle and end position
Case 1 - Moving with the keyboard:
-
Move slider to start position, and check if the current position equals the beginning value
-
Move the slider to middle position, and check if the current position equals the middle value
-
Move slider to end position, and check if the current position equals the end value
-
Try to move slider before start position, and check if the current position equals the beginning value
-
Try to move slider after end position, and check if the current position equals the end value
-
Try to move the slider to an improperly defined position between start and middle, and check if the current position equals the corrected value
-
Try to move the slider to an improperly defined random position, and check if the current position equals the corrected value
-
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()); } }
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.
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); } }
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.
Before all tests: Open The Internet Main Page
Before each case: Go to Sortable Data Tables Page
Case 1:
-
Choose a random table
-
Sort first column "Last Name" in ascending order
-
Check if column header class contains "headerSortDown"
-
Save column content to the List
-
Create List copy and sort it
-
Compare sorted values and values from the table
Case 2:
-
Choose a random table
-
Sort second column "First Name" in descending order
-
Check if column header class contains "headerSortUp"
-
Save column content to the List
-
Create List copy and sort it then reverse it
-
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); } }
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:
-
Open developer tools
-
Go to Network tab
-
Click request name
-
Find a code number in Headers section
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(); } }
Before all tests: Open The Internet Main Page, go to Status Codes page
Steps:
For each status code
-
Click code link
-
Check if the page is loaded with an expected code number
-
Check if the displayed code number equals the expected number
-
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
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(); } }
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.
Dynamic variable values are stored under path \src\resources\enviroments\environments.csv.
By default, the environment takes value from DEV column.
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();
Create a selector for every interactable element on a webpage using By type. Find elements and it’s attributes using browser developer mode (F12).
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']");
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.
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(); }
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 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
As an example to test we will use MyThaiStar booking page.
In order to book a table, do the following steps:
-
Open MyThaiStar Book Table Page
-
Enter booking data: Date and time, Name, Email and number of Table guests
-
Click Accept terms
-
Click Book table
-
Display confirmation box and send booking
-
Check if the booking was successful.
You can go through these steps manually and doublecheck the result.
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?
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(); }
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 } }
After the click on Send button - the green confirmation dialogue appears with the message "Table successfully booked":
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 }
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() { } }
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 }
Run the test by right-clicking on the test method → Run as → JUnit test.