Java tutorial
/* * Copyright Technophobia Ltd 2012 * * This file is part of Substeps. * * Substeps is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Substeps is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Substeps. If not, see <http://www.gnu.org/licenses/>. */ package com.technophobia.webdriver.substeps.impl; import com.google.common.io.Files; import com.technophobia.substeps.model.Configuration; import com.technophobia.substeps.model.SubSteps; import com.technophobia.substeps.model.SubSteps.Step; import com.technophobia.substeps.model.SubSteps.StepImplementations; import com.technophobia.webdriver.substeps.runner.Condition; import com.technophobia.webdriver.substeps.runner.DefaultExecutionSetupTearDown; import com.technophobia.webdriver.substeps.runner.WebdriverSubstepsPropertiesConfiguration; import com.technophobia.webdriver.util.WebDriverSubstepsBy; import org.junit.Assert; import org.openqa.selenium.*; import org.openqa.selenium.WebDriver.TargetLocator; import org.openqa.selenium.interactions.Actions; import org.openqa.selenium.support.ui.ExpectedConditions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import static org.hamcrest.CoreMatchers.is; @StepImplementations(requiredInitialisationClasses = DefaultExecutionSetupTearDown.class) public class ActionWebDriverSubStepImplementations extends AbstractWebDriverSubStepImplementations { private static final Logger logger = LoggerFactory.getLogger(ActionWebDriverSubStepImplementations.class); private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMMddHHmm"); private final FinderWebDriverSubStepImplementations locator; public ActionWebDriverSubStepImplementations() { this.locator = new FinderWebDriverSubStepImplementations(); } /** * Navigate to a url, if the url begins with http or file, the url will be * used as is, if a relative url is specified then it will be prepended with * the base url property * * @example NavigateTo /myApp (will navigate to http://localhost/myApp if * base.url is set to http://localhost) * @section Location * * @param url * the url */ @Step("NavigateTo ([^\"]*)") public void navigateTo(final String url) { logger.debug("About to navigate to " + url); if (url.startsWith("file") || url.startsWith("http")) { webDriver().get(url); } else { webDriver().get(normaliseURL(url)); } } /** * Navigate to a url specified by a property in the config files * * @example NavigateTo url property "login.url" * * @section Location * @param urlProperty the property to lookup */ @SubSteps.Step("NavigateTo url property \"([^\"]*)\"") public void navigateToProperty(final String urlProperty) { final String url = Configuration.INSTANCE.getString(urlProperty); logger.debug("About to navigate to base url : " + url); if (url.startsWith("file") || url.startsWith("http")) { webDriver().get(url); } else { webDriver().get(normaliseURL(url)); } } /** * Find an element by id, then click it. * * @example ClickById login * @section Clicks * * @param id * the id */ @Step("ClickById ([^\"]*)") public void clickById(final String id) { logger.debug("About to click item with id " + id); this.locator.findById(id); click(); } /** * Click (the current element) * * @example Click * @section Clicks */ @Step("Click") public void click() { logger.debug("About to click on current element"); clickWhenClickable(); } /** * Clicks (the current element) when the element can be clicked (visibility, enabled etc) * * @example ClickWhenClickable * @section Clicks */ @SubSteps.Step("ClickWhenClickable") public void clickWhenClickable() { WebElement currentElement = webDriverContext().getCurrentElement(); waitUntil(ExpectedConditions.elementToBeClickable(currentElement)); currentElement.click(); } /** * Finds a button that contains the specified text, waits until the element is clickable, then clicks it. * * @example ClickButton containing "button text" * * @section Clicks * @param text the text to partially match against the button text */ @SubSteps.Step("ClickButton containing \"([^\"]*)\"") public void clickButtonContainingText(String text) { final By by = WebDriverSubstepsBy.ByTagContainingText("button", text); waitFor(by, "expecting an element with tag", "button", "and text", text); logger.debug("about to wait until element clickable"); waitUntil(ExpectedConditions.elementToBeClickable(by)); logger.debug("element should be clickable"); this.webDriverContext().getCurrentElement().click(); } /** * Click the link "(....)" as it appears on the page * * @example ClickLink "Contracts" * @section Clicks * @param linkText * the link text */ @Step("ClickLink \"([^\"]*)\"") public void clickLink(final String linkText) { logger.debug("About to click link with text " + linkText); webDriverContext().setCurrentElement(null); final WebElement elem = webDriver().findElement(By.linkText(linkText)); Assert.assertNotNull("expecting to find a link: " + linkText, elem); webDriverContext().setCurrentElement(elem); elem.click(); } /** * Click a button that has the text, NB surrounding quotes are optional * * @example ClickButton "submit button" * @section Clicks * @param buttonText * the button text */ @SubSteps.Step("ClickButton \"?([^\"]*)\"?") public void clickButton(String buttonText) { final By by = WebDriverSubstepsBy.ByTagAndWithText("button", buttonText); waitFor(by, "expecting an element with tag", "button", "and text", buttonText); logger.debug("about to wait until element clickable"); waitUntil(ExpectedConditions.elementToBeClickable(by)); logger.debug("element should be clickable"); this.webDriverContext().getCurrentElement().click(); } /** * Finds an input element with the specified value, then clicks it. * * @section Form * @example ClickSubmitButton "Submit" * * @param buttonText the button text */ @Step("ClickSubmitButton \"([^\"]*)\"") public void clickInput(final String buttonText) { logger.debug("About to click submit button with text " + buttonText); webDriverContext().setCurrentElement(null); By by = WebDriverSubstepsBy.ByTagAndAttributes("input", "value=\"" + buttonText + "\""); WebElement webElement = waitFor(by, "expecting an input element with value=" + buttonText); webElement.click(); } /** * Wait for the specified number of milliseconds * * @example WaitFor 10 * @section Location * @param value * the value */ @Step("WaitFor ([^\"]*)") public void waitFor(final String value) { logger.debug("About to wait for " + value + "ms"); final long ms = Long.parseLong(value); try { Thread.sleep(ms); } catch (final InterruptedException e) { logger.debug("interupt ex"); // do we care? } } /** * Wait for the page title to change to the specified value * * @example WaitForPageTitle "My Home Page" * @section Location * * @param expectedTitle * the expected title */ @Step("WaitForPageTitle \"([^\"]*)\"") public void waitForPageTitle(final String expectedTitle) { logger.debug("Waiting for " + expectedTitle + " page"); final boolean conditionMet = webDriverContext().waitForCondition(new Condition() { public boolean conditionMet() { final String pageTitle = webDriver().getTitle(); logger.debug(String.format("wait for page. Expected='%s', actual='%s'", expectedTitle, pageTitle)); return pageTitle.equals(expectedTitle); } }); if (!conditionMet) { logger.debug(expectedTitle + " page not found"); // Assert.fail("Webpage was not found within the time frame set."); } Assert.assertTrue(conditionMet); } private String normaliseURL(final String relativeURL) { return normalise(WebdriverSubstepsPropertiesConfiguration.INSTANCE.baseURL() + relativeURL); } private String normalise(final String urlToNormalise) { try { return new URI(urlToNormalise).toString(); } catch (final URISyntaxException ex) { throw new IllegalStateException("The url " + urlToNormalise + " is invalid.", ex); } } /** * Performs a double click on the current element (set with a previous Find * method). * * @example PerformDoubleClick * @section Clicks * */ @Step("PerformDoubleClick") public void doDoubleClick() { final Actions actions = new Actions(webDriver()); actions.doubleClick(webDriverContext().getCurrentElement()); actions.perform(); } /** * Performs a context click (typically right click, unless this has been * changed by the user) on the current element. * * @example PerformContextClick * @section Clicks * */ @Step("PerformContextClick") public void performContextClick() { final Actions actions = new Actions(webDriver()); actions.contextClick(webDriverContext().getCurrentElement()); actions.perform(); } /** * Dismisses an Alert with specific text * @section Clicks * @example DismissAlert with message "Popup" * * @param message the expected alert text */ @Step("DismissAlert with message \"([^\"]*)\"") public void dismissAlertWithMessage(final String message) { // Get a handle to the open alert, prompt or confirmation final Alert alert = webDriverContext().getWebDriver().switchTo().alert(); // this will throw a org.openqa.selenium.NoAlertPresentException if no // alert is present logger.debug("alert says: " + alert.getText()); Assert.assertThat(alert.getText(), is(message)); // And acknowledge the alert (equivalent to clicking "OK") alert.accept(); } /** * Asserts that the current element is visible, it will wait until this is true * @example AssertCurrentElement is visible * @section Assertions */ @Step("AssertCurrentElement is visible") public void assertCurrentElementIsVisible() { WebElement currentElement = webDriverContext().getCurrentElement(); waitUntil(ExpectedConditions.visibilityOf(currentElement)); } /** * Waits until the current element is invisible, either visibility: hidden or display:none * * @example AssertCurrentElement is invisible * @section Assertions * */ @Step("AssertCurrentElement is invisible") public void assertCurrentElementIsInVisible() { WebElement currentElement = webDriverContext().getCurrentElement(); List<WebElement> elems = new ArrayList<>(); elems.add(currentElement); waitUntil(ExpectedConditions.invisibilityOfAllElements(elems)); } /** * Invoke the webdriver Javascript executor to run a line of javascript * * @section Actions * @example ExecuteJavascript document.getElementById("id-for-js-manipulation").innerHTML = "js fiddled" * * @param js the javascript expression */ @SubSteps.Step("ExecuteJavascript (.*)$") public void executeJavaScript(String js) { ((JavascriptExecutor) webDriver()).executeScript(js); } /** * Takes a screenshot and writes to a file with the specified prefix, appending a timestamp of the format (yyMMddHHmm) * * @example TakeScreenshot with prefix "self-test" * @section Actions * * @param filePrefix the filename prefix */ @SubSteps.Step("TakeScreenshot with prefix \"([^\"]*)\"") public void takeScreenshot(String filePrefix) { logger.debug("taking screenshot.."); LocalDateTime timePoint = LocalDateTime.now(); timePoint.getMinute(); String formattedDate = timePoint.format(formatter); File out = new File(filePrefix + "_" + formattedDate + ".png"); try { Files.write(getScreenshotBytes(), out); } catch (IOException e) { e.printStackTrace(); } } }