Java tutorial
/** * Copyright (c) 2002-2015, JWebUnit team. * * This file is part of JWebUnit. * * JWebUnit 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. * * JWebUnit 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 General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with JWebUnit. If not, see <http://www.gnu.org/licenses/>. */ package net.sourceforge.jwebunit.webdriver; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.WebResponse; import net.lightbody.bmp.core.har.Har; import net.lightbody.bmp.proxy.LegacyProxyServer; import net.lightbody.bmp.proxy.ProxyServer; import net.lightbody.bmp.proxy.http.BrowserMobHttpRequest; import net.lightbody.bmp.proxy.http.BrowserMobHttpResponse; import net.lightbody.bmp.proxy.http.RequestInterceptor; import net.lightbody.bmp.proxy.http.ResponseInterceptor; import net.lightbody.bmp.proxy.jetty.util.MultiException; import net.sourceforge.jwebunit.api.HttpHeader; import net.sourceforge.jwebunit.api.IElement; import net.sourceforge.jwebunit.api.ITestingEngine; import net.sourceforge.jwebunit.exception.ExpectedJavascriptAlertException; import net.sourceforge.jwebunit.exception.ExpectedJavascriptConfirmException; import net.sourceforge.jwebunit.exception.ExpectedJavascriptPromptException; import net.sourceforge.jwebunit.exception.TestingEngineResponseException; import net.sourceforge.jwebunit.html.Cell; import net.sourceforge.jwebunit.html.Row; import net.sourceforge.jwebunit.html.Table; import net.sourceforge.jwebunit.javascript.JavascriptAlert; import net.sourceforge.jwebunit.javascript.JavascriptConfirm; import net.sourceforge.jwebunit.javascript.JavascriptPrompt; import net.sourceforge.jwebunit.util.TestContext; import org.apache.commons.lang.StringUtils; import org.apache.http.Header; import org.apache.http.HttpStatus; import org.apache.regexp.RE; import org.apache.regexp.RESyntaxException; import org.openqa.selenium.By; import org.openqa.selenium.Cookie; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.NoSuchWindowException; import org.openqa.selenium.Proxy; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.htmlunit.HtmlUnitDriver; import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.support.ui.Select; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; /** * Acts as the wrapper for Webdriver access. A testing engine is initialized with a given URL, and maintains * conversational state as the dialog progresses through link navigation, form submission, etc. * * @author Julien Henry */ public class WebDriverTestingEngineImpl implements ITestingEngine { /** * Logger for this class. */ private final Logger logger = LoggerFactory.getLogger(WebDriverTestingEngineImpl.class); private LegacyProxyServer proxyServer; private WebDriver driver; private TestContext testContext; private static final int TRY_COUNT = 50; private static final int DEFAULT_PORT = 8183; private static final Random RANDOM = new Random(); private BrowserMobHttpResponse response; // The xpath string that identifie the current form // ie : @name='myForm' private String formIdent; private boolean throwExceptionOnScriptError = true;// TODO private boolean ignoreFailingStatusCodes = false; /** * Is Javascript enabled. */ private boolean jsEnabled = true; public WebDriverTestingEngineImpl() { } public void beginAt(URL aInitialURL, TestContext aTestContext) throws TestingEngineResponseException { this.setTestContext(aTestContext); // start the proxy Proxy proxy = startBrowserMobProxy(); DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability(CapabilityType.PROXY, proxy); capabilities.setCapability(CapabilityType.SUPPORTS_JAVASCRIPT, jsEnabled); capabilities.setBrowserName("htmlunit"); capabilities.setVersion("firefox"); driver = new HtmlUnitDriver(capabilities); // Reset form formIdent = null; // Deal with cookies for (javax.servlet.http.Cookie c : aTestContext.getCookies()) { // FIXME Hack for BrowserMob String domain = c.getDomain(); if ("localhost".equals(domain)) { domain = null; } if ("".equals(domain)) { domain = null; } Date expiry = null; if (c.getMaxAge() != -1) { Calendar cal = Calendar.getInstance(); cal.add(Calendar.SECOND, c.getMaxAge()); expiry = cal.getTime(); } driver.manage().addCookie(new org.openqa.selenium.Cookie(c.getName(), c.getValue(), domain, c.getPath() != null ? c.getPath() : "", expiry, c.getSecure())); } gotoPage(aInitialURL); } private Proxy startBrowserMobProxy() { for (int i = 1; i <= TRY_COUNT; i++) { int port = getRandomPort(); proxyServer = new ProxyServer(); proxyServer.setPort(port); try { proxyServer.start(); proxyServer.addResponseInterceptor(new ResponseInterceptor() { @Override public void process(BrowserMobHttpResponse response, Har har) { WebDriverTestingEngineImpl.this.response = response; } }); if (testContext.getRequestHeaders() != null && !testContext.getRequestHeaders().isEmpty()) { proxyServer.addRequestInterceptor(new RequestInterceptor() { @Override public void process(BrowserMobHttpRequest request, Har har) { for (Map.Entry<String, String> requestHeader : testContext.getRequestHeaders() .entrySet()) { request.addRequestHeader(requestHeader.getKey(), requestHeader.getValue()); } } }); } if (StringUtils.isNotBlank(testContext.getUserAgent())) { proxyServer.addRequestInterceptor(new RequestInterceptor() { @Override public void process(BrowserMobHttpRequest request, Har har) { request.getMethod().removeHeaders("User-Agent"); request.addRequestHeader("User-Agent", testContext.getUserAgent()); } }); } return proxyServer.seleniumProxy(); } catch (Exception e) { if (i < TRY_COUNT) { logger.error("Error while starting BrowserMob proxy on port " + port + ". Retry...: " + e.getMessage(), e); if (e instanceof MultiException) { Exception e1 = ((MultiException) e).getException(0); logger.error("First exception: " + e1.getMessage(), e1); } continue; } } } throw new RuntimeException("Unable to start BrowserMob proxy after " + TRY_COUNT + " retries"); } private static int getRandomPort() { synchronized (RANDOM) { return DEFAULT_PORT + RANDOM.nextInt(1000); } } public void setTestContext(TestContext testContext) { this.testContext = testContext; } public void closeBrowser() throws ExpectedJavascriptAlertException, ExpectedJavascriptConfirmException, ExpectedJavascriptPromptException { formIdent = null; if (driver != null) { driver.quit(); driver = null; } if (proxyServer != null) { try { proxyServer.stop(); proxyServer = null; } catch (Exception e) { logger.error("Error while stopping proxy", e); throw new RuntimeException("Error while stopping proxy", e); } } } public void gotoPage(URL url) throws TestingEngineResponseException { formIdent = null; // Big hack for browsermob String urlStr = url.toString().replace("http://localhost", "http://127.0.0.1"); driver.get(urlStr); throwFailingHttpStatusCodeExceptionIfNecessary(getServerResponseCode(), urlStr); } /** * Copied from {@link WebClient#throwFailingHttpStatusCodeExceptionIfNecessary(WebResponse)} */ private void throwFailingHttpStatusCodeExceptionIfNecessary(int statusCode, String url) { final boolean successful = (statusCode >= HttpStatus.SC_OK && statusCode < HttpStatus.SC_MULTIPLE_CHOICES) || statusCode == HttpStatus.SC_USE_PROXY || statusCode == HttpStatus.SC_NOT_MODIFIED; if (!this.ignoreFailingStatusCodes && !successful) { throw new TestingEngineResponseException(statusCode, "unexpected status code [" + statusCode + "] at URL: [" + url + "]"); } } public void setScriptingEnabled(boolean value) { // This variable is used to set Javascript before wc is instancied jsEnabled = value; if (driver != null && driver instanceof HtmlUnitDriver) { ((HtmlUnitDriver) driver).setJavascriptEnabled(value); } } public void setThrowExceptionOnScriptError(boolean value) { this.throwExceptionOnScriptError = true; } public List<javax.servlet.http.Cookie> getCookies() { List<javax.servlet.http.Cookie> result = new LinkedList<javax.servlet.http.Cookie>(); Set<Cookie> cookies = driver.manage().getCookies(); for (Cookie cookie : cookies) { javax.servlet.http.Cookie c = new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue()); c.setDomain(cookie.getDomain()); Date expire = cookie.getExpiry(); if (expire == null) { c.setMaxAge(-1); } else { Date now = Calendar.getInstance().getTime(); // Convert milli-second to second Long second = Long.valueOf((expire.getTime() - now.getTime()) / 1000); c.setMaxAge(second.intValue()); } c.setPath(cookie.getPath()); c.setSecure(cookie.isSecure()); result.add(c); } return result; } public boolean hasWindow(String windowName) { // Save current handle String current = driver.getWindowHandle(); try { driver.switchTo().window(windowName); driver.switchTo().window(current); return true; } catch (NoSuchWindowException e) { return false; } } public boolean hasWindowByTitle(String windowTitle) { // Save current handle String current = driver.getWindowHandle(); for (String handle : driver.getWindowHandles()) { driver.switchTo().window(handle); if (driver.getTitle().equals(windowTitle)) { driver.switchTo().window(current); return true; } } driver.switchTo().window(current); return false; } public void gotoWindow(String windowName) { driver.switchTo().window(windowName); } public void gotoWindowByTitle(String title) { // Save current handle String current = driver.getWindowHandle(); for (String handle : driver.getWindowHandles()) { driver.switchTo().window(handle); if (title.equals(driver.getTitle())) { return; } } driver.switchTo().window(current); throw new RuntimeException("No window found with title [" + title + "]"); } public void gotoWindow(int windowID) { Set<String> handles = driver.getWindowHandles(); driver.switchTo().window(handles.toArray(new String[handles.size()])[windowID]); } public void gotoRootWindow() { driver.switchTo().defaultContent(); } public int getWindowCount() { return driver.getWindowHandles().size(); } public void closeWindow() { formIdent = null; driver.close(); // FIXME Issue 1466 & 2834 if (getWindowCount() > 0) { driver.switchTo().window(driver.getWindowHandles().iterator().next()); } } public boolean hasFrame(String frameNameOrId) { List<WebElement> frameset = driver.findElements(By.tagName("frame")); for (WebElement frame : frameset) { if (frameNameOrId.equals(frame.getAttribute("name")) || frameNameOrId.equals(frame.getAttribute("id"))) { return true; } } return false; } public void gotoFrame(String frameNameOrId) { driver.switchTo().frame(frameNameOrId); } public void setWorkingForm(int index) { formIdent = "position()=" + (index + 1); } public void setWorkingForm(String nameOrId, int index) { if (nameOrId != null) { formIdent = "(@name=" + escapeQuotes(nameOrId) + " or @id=" + escapeQuotes(nameOrId) + ")][position()=" + (index + 1); } else { formIdent = null; } } protected String formSelector() { if (formIdent == null) { return "//form"; } return "//form[" + formIdent + "]"; } public boolean hasForm() { return hasElementByXPath("//form"); } public boolean hasForm(String nameOrID) { return hasElementByXPath( "//form[@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + "]"); } public boolean hasForm(String nameOrID, int index) { return hasElementByXPath("//form[@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + "][position()=" + (index + 1) + "]"); } public boolean hasFormParameterNamed(String paramName) { return getWebElementByXPath("//*[@name=" + escapeQuotes(paramName) + "]", false, true) != null; } private WebElement getWebElementByXPath(String xpathAfterForm, boolean searchOnlyInCurrentForm, boolean overrideWorkingForm) { // First try the current form if (formIdent != null) { try { return driver.findElement(By.xpath("//form[" + formIdent + "]" + xpathAfterForm)); } catch (NoSuchElementException ex) { if (searchOnlyInCurrentForm) { return null; } } } // not in the current form: try other forms List<WebElement> forms = driver.findElements(By.tagName("form")); int index = 0; for (WebElement f : forms) { try { WebElement e = driver .findElement(By.xpath("//form[position()=" + (index + 1) + "]" + xpathAfterForm)); if (overrideWorkingForm) { setWorkingForm(index); } return e; } catch (NoSuchElementException ex) { index++; } } // now look everywhere (maybe outside of form) try { return driver.findElement(By.xpath("//body" + xpathAfterForm)); } catch (NoSuchElementException ex) { return null; } } private List<WebElement> getWebElementsByXPath(String xpathAfterForm) { try { return driver.findElements(By.xpath(formSelector() + xpathAfterForm)); } catch (NoSuchElementException e) { return null; } } public String getTextFieldValue(String paramName) { WebElement e = getTextField(paramName); return e.getAttribute("value"); } public String getHiddenFieldValue(String paramName) { WebElement e = getWebElementByXPath("//input[@type='hidden' and @name=" + escapeQuotes(paramName) + "]", false, true); return e.getAttribute("value"); } public void setTextField(String inputName, String text) { WebElement e = getTextField(inputName); e.clear(); e.sendKeys(text); } /** * Look for any text field (input text, input password, textarea, file input). */ private WebElement getTextField(String paramName) { WebElement e = getWebElementByXPath("//input[@type='text' and @name=" + escapeQuotes(paramName) + "]", false, true); if (e == null) { e = getWebElementByXPath("//textarea[@name=" + escapeQuotes(paramName) + "]", false, true); } if (e == null) { e = getWebElementByXPath("//input[@type='file' and @name=" + escapeQuotes(paramName) + "]", false, true); } if (e == null) { e = getWebElementByXPath("//input[@type='password' and @name=" + escapeQuotes(paramName) + "]", false, true); } return e; } public void setHiddenField(String inputName, String text) { WebElement e = getWebElementByXPath("//input[@type='hidden' and @name=" + escapeQuotes(inputName) + "]", false, true); ((JavascriptExecutor) driver).executeScript("arguments[0].value=" + escapeQuotes(text), e); } public String[] getSelectOptionValues(String selectName) { return getSelectOptionValues(selectName, 0); } public String[] getSelectOptionValues(String selectName, int index) { Select select = new Select(getWebElementByXPath( "//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true)); ArrayList<String> result = new ArrayList<String>(); for (WebElement opt : select.getOptions()) { result.add(opt.getAttribute("value")); } return result.toArray(new String[result.size()]); } public String[] getSelectedOptions(String selectName) { return getSelectedOptions(selectName, 0); } private String[] getSelectedOptions(Select select) { // FIXME http://code.google.com/p/selenium/issues/detail?id=2295 String[] result = new String[select.getAllSelectedOptions().size()]; int i = 0; for (WebElement opt : select.getAllSelectedOptions()) { result[i++] = opt.getAttribute("value"); } return result; } public String[] getSelectedOptions(String selectName, int index) { Select select = new Select(getWebElementByXPath( "//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true)); return getSelectedOptions(select); } private String getSelectOptionValueForLabel(Select select, String label) { for (WebElement opt : select.getOptions()) { if (opt.getText().equals(label)) { return opt.getAttribute("value"); } } throw new RuntimeException("Unable to find option " + label); } private String getSelectOptionLabelForValue(Select select, String value) { for (WebElement opt : select.getOptions()) { if (opt.getAttribute("value").equals(value)) { return opt.getText(); } } throw new RuntimeException("Unable to find option " + value); } public String getSelectOptionLabelForValue(String selectName, String optionValue) { Select select = new Select( getWebElementByXPath("//select[@name=" + escapeQuotes(selectName) + "]", true, true)); return getSelectOptionLabelForValue(select, optionValue); } public String getSelectOptionLabelForValue(String selectName, int index, String optionValue) { Select select = new Select(getWebElementByXPath( "//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true)); return getSelectOptionLabelForValue(select, optionValue); } public String getSelectOptionValueForLabel(String selectName, String optionLabel) { Select select = new Select( getWebElementByXPath("//select[@name=" + escapeQuotes(selectName) + "]", true, true)); return getSelectOptionValueForLabel(select, optionLabel); } public String getSelectOptionValueForLabel(String selectName, int index, String optionLabel) { Select select = new Select(getWebElementByXPath( "//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true)); return getSelectOptionValueForLabel(select, optionLabel); } public void selectOptions(String selectName, String[] optionValues) { selectOptions(selectName, 0, optionValues); } public void selectOptions(String selectName, int index, String[] optionValues) { Select select = new Select(getWebElementByXPath( "//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true)); if (!select.isMultiple() && optionValues.length > 1) throw new RuntimeException("Multiselect not enabled"); for (String option : optionValues) { boolean found = false; for (WebElement opt : select.getOptions()) { if (opt.getAttribute("value").equals(option)) { select.selectByValue(option); found = true; break; } } if (!found) { throw new RuntimeException("Option " + option + " not found"); } } } public void unselectOptions(String selectName, String[] optionValues) { unselectOptions(selectName, 0, optionValues); } public void unselectOptions(String selectName, int index, String[] optionValues) { Select select = new Select(getWebElementByXPath( "//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true)); if (!select.isMultiple() && optionValues.length > 1) throw new RuntimeException("Multiselect not enabled"); for (String option : optionValues) { boolean found = false; for (WebElement opt : select.getOptions()) { if (opt.getAttribute("value").equals(option)) { select.deselectByValue(option); found = true; break; } } if (!found) { throw new RuntimeException("Option " + option + " not found"); } } } public boolean hasSelectOption(String selectName, String optionLabel) { return hasSelectOption(selectName, 0, optionLabel); } public boolean hasSelectOptionValue(String selectName, String optionValue) { return hasSelectOptionValue(selectName, 0, optionValue); } public boolean hasSelectOption(String selectName, int index, String optionLabel) { Select select = new Select(getWebElementByXPath( "//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true)); for (WebElement opt : select.getOptions()) { if (opt.getText().equals(optionLabel)) { return true; } } return false; } public boolean hasSelectOptionValue(String selectName, int index, String optionValue) { Select select = new Select(getWebElementByXPath( "//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true)); for (WebElement opt : select.getOptions()) { if (opt.getAttribute("value").equals(optionValue)) { return true; } } return false; } public boolean isCheckboxSelected(String checkBoxName) { WebElement e = getWebElementByXPath( "//input[@type='checkbox' and @name=" + escapeQuotes(checkBoxName) + "]", true, true); return e.isSelected(); } public boolean isCheckboxSelected(String checkBoxName, String checkBoxValue) { WebElement e = getWebElementByXPath("//input[@type='checkbox' and @name=" + escapeQuotes(checkBoxName) + " and @value=" + escapeQuotes(checkBoxValue) + "]", true, true); return e.isSelected(); } public void checkCheckbox(String checkBoxName) { WebElement e = getWebElementByXPath( "//input[@type='checkbox' and @name=" + escapeQuotes(checkBoxName) + "]", true, true); if (!e.isSelected()) { e.click(); } } public void checkCheckbox(String checkBoxName, String checkBoxValue) { WebElement e = getWebElementByXPath("//input[@type='checkbox' and @name=" + escapeQuotes(checkBoxName) + " and @value=" + escapeQuotes(checkBoxValue) + "]", true, true); if (!e.isSelected()) { e.click(); } } public void uncheckCheckbox(String checkBoxName) { WebElement e = getWebElementByXPath( "//input[@type='checkbox' and @name=" + escapeQuotes(checkBoxName) + "]", true, true); if (e.isSelected()) { e.click(); } } public void uncheckCheckbox(String checkBoxName, String value) { WebElement e = getWebElementByXPath("//input[@type='checkbox' and @name=" + escapeQuotes(checkBoxName) + " and @value=" + escapeQuotes(value) + "]", true, true); if (e.isSelected()) { e.click(); } } public void clickRadioOption(String radioGroup, String radioOptionValue) { WebElement e = getWebElementByXPath("//input[@type='radio' and @name=" + escapeQuotes(radioGroup) + " and @value=" + escapeQuotes(radioOptionValue) + "]", false, true); e.click(); } public boolean hasRadioOption(String radioGroup, String radioOptionValue) { WebElement e = getWebElementByXPath("//input[@type='radio' and @name=" + escapeQuotes(radioGroup) + " and @value=" + escapeQuotes(radioOptionValue) + "]", false, true); return e != null; } public String getSelectedRadio(String radioGroup) { List<WebElement> radios = getWebElementsByXPath( "/input[@type='radio' and @name=" + escapeQuotes(radioGroup) + "]"); for (WebElement r : radios) { if (r.isSelected()) { return r.getAttribute("value"); } } return null; } public boolean hasSubmitButton() { return (getWebElementByXPath("//input[@type='submit' or @type='image']", true, true) != null) || (getWebElementByXPath("//button[@type='submit']", false, true) != null); } public boolean hasSubmitButton(String nameOrID) { return (getWebElementByXPath("//input[(@type='submit' or @type='image') and (@name=" + escapeQuotes(nameOrID) + " or @id=" + nameOrID + ")]", true, true) != null) || (getWebElementByXPath("//button[@type='submit' and (@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + ")]", true, true) != null); } public boolean hasSubmitButton(String nameOrID, String value) { return (getWebElementByXPath( "//input[(@type='submit' or @type='image') and (@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + ") and @value=" + escapeQuotes(value) + "]", true, true) != null) || (getWebElementByXPath( "//button[@type='submit' and (@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + ") and @value=" + escapeQuotes(value) + "]", true, true) != null); } public void submit() { WebElement e = getWebElementByXPath("//input[@type='submit' or @type='image']", true, true); if (e == null) { e = getWebElementByXPath("//button[@type='submit']", true, true); } e.submit(); throwFailingHttpStatusCodeExceptionIfNecessary(getServerResponseCode(), driver.getCurrentUrl()); } public void submit(String nameOrID) { WebElement e = getWebElementByXPath("//input[(@type='submit' or @type='image') and (@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + ")]", true, true); if (e == null) { e = getWebElementByXPath("//button[@type='submit' and (@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + ")]", true, true); } e.submit(); throwFailingHttpStatusCodeExceptionIfNecessary(getServerResponseCode(), driver.getCurrentUrl()); } public void submit(String buttonName, String buttonValue) { WebElement e = getWebElementByXPath( "//input[(@type='submit' or @type='image') and (@name=" + escapeQuotes(buttonName) + " or @id=" + escapeQuotes(buttonName) + ") and @value=" + escapeQuotes(buttonValue) + "]", true, true); if (e == null) { e = getWebElementByXPath( "//button[@type='submit' and (@name=" + escapeQuotes(buttonName) + " or @id=" + escapeQuotes(buttonName) + ") and @value=" + escapeQuotes(buttonValue) + "]", true, true); } e.submit(); throwFailingHttpStatusCodeExceptionIfNecessary(getServerResponseCode(), driver.getCurrentUrl()); } public boolean hasResetButton() { return getWebElementByXPath("//input[@type='reset']", false, true) != null; } public boolean hasResetButton(String nameOrID) { return getWebElementByXPath("//input[@type='reset' and (@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + ")]", true, true) != null; } public void reset() { getWebElementByXPath("//input[@type='reset']", true, true).click(); ; } private WebElement getButton(String nameOrID) { WebElement e = getWebElementByXPath( "//input[(@type='submit' or @type='image' or @type='reset' or @type='button') and (@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + ")]", false, true); if (e == null) { e = getWebElementByXPath( "//button[@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + "]", false, true); } return e; } private WebElement getButtonWithText(String text) { WebElement e = getWebElementByXPath( "//input[(@type='submit' or @type='reset' or @type='button') and contains(@value," + escapeQuotes(text) + ")]", false, true); if (e == null) { e = getWebElementByXPath("//button[contains(.," + escapeQuotes(text) + ")]", false, true); } return e; } public boolean hasButtonWithText(String text) { return getButtonWithText(text) != null; } public boolean hasButton(String buttonId) { return getButton(buttonId) != null; } public void clickButton(String buttonId) { getButton(buttonId).click(); } public void clickButtonWithText(String buttonValueText) { getButtonWithText(buttonValueText).click(); } public URL getPageURL() { try { return new URL(driver.getCurrentUrl()); } catch (MalformedURLException ex) { throw new RuntimeException(ex); } } public String getPageText() { try { return driver.findElement(By.tagName("body")).getText(); } catch (Exception e) { // Maybe this is not HTML return driver.getPageSource(); } } public String getPageSource() { return driver.getPageSource(); // Do not work when there are requests following loading of main page (like frames) // String encoding = "ISO-8859-1"; // if (response.getEntity().getContentEncoding() != null) { // encoding = response.getEntity().getContentEncoding().getValue(); // } // // try { // return IOUtils.toString(response.getEntity().getContent(), encoding); // } // catch (IOException e) { // throw new RuntimeException(e); // } } public String getPageTitle() { return driver.getTitle(); } public String getServerResponse() { throw new UnsupportedOperationException("Not supported yet."); } public InputStream getInputStream() { try { return response.getRawResponse().getEntity().getContent(); } catch (Exception e) { throw new TestingEngineResponseException(e); } } public InputStream getInputStream(URL url) throws TestingEngineResponseException { try { return url.openStream();// TODO support proxy } catch (IOException e) { throw new TestingEngineResponseException(e); } } public boolean hasTable(String tableSummaryNameOrId) { return getHtmlTable(tableSummaryNameOrId) != null; } public Table getTable(String tableSummaryNameOrId) { WebElement table = getHtmlTable(tableSummaryNameOrId); Table result = new Table(); List<WebElement> trs = table.findElements(By.xpath("tr | tbody/tr")); for (int i = 0; i < trs.size(); i++) { Row newRow = new Row(); WebElement tr = trs.get(i); List<WebElement> tds = tr.findElements(By.xpath("td | th")); for (WebElement td : tds) { int colspan; try { colspan = Integer.valueOf(td.getAttribute("colspan")); } catch (NumberFormatException e) { colspan = 1; } int rowspan; try { rowspan = Integer.valueOf(td.getAttribute("rowspan")); } catch (NumberFormatException e) { rowspan = 1; } newRow.appendCell(new Cell(td.getText(), colspan, rowspan)); } result.appendRow(newRow); } return result; } /** * Return the Webdriver WebElement object representing a specified table in the current response. Null is returned if a * parsing exception occurs looking for the table or no table with the id or summary could be found. * * @param tableSummaryOrId summary or id of the table to return. */ private WebElement getHtmlTable(String tableSummaryOrId) { try { return driver.findElement(By.xpath("(//table[@id=" + escapeQuotes(tableSummaryOrId) + " or @summary=" + escapeQuotes(tableSummaryOrId) + "])")); } catch (NoSuchElementException e) { return null; } } private WebElement getLinkWithImage(String filename, int index) { try { return driver.findElement( By.xpath("(//a[img[contains(@src," + escapeQuotes(filename) + ")]])[" + (index + 1) + "]")); } catch (NoSuchElementException e) { return null; } } private WebElement getLinkWithText(String linkText, int index) { List<WebElement> lnks = driver.findElements(By.xpath("//a")); int count = 0; for (WebElement lnk : lnks) { if ((lnk.getText().indexOf(linkText) >= 0) && (count++ == index)) { return lnk; } } return null; } private WebElement getLinkWithExactText(String linkText, int index) { List<WebElement> lnks = driver.findElements(By.xpath("//a")); int count = 0; for (WebElement lnk : lnks) { if (lnk.getText().equals(linkText) && (count++ == index)) { return lnk; } } return null; } public boolean hasLinkWithText(String linkText, int index) { return getLinkWithText(linkText, index) != null; } public boolean hasLinkWithExactText(String linkText, int index) { return getLinkWithExactText(linkText, index) != null; } public boolean hasLinkWithImage(String imageFileName, int index) { return getLinkWithImage(imageFileName, index) != null; } public boolean hasLink(String anId) { try { driver.findElement(By.xpath("//a[@id='" + anId + "']")); return true; } catch (NoSuchElementException e) { return false; } } public void clickLinkWithText(String linkText, int index) { WebElement link = getLinkWithText(linkText, index); if (link == null) { throw new RuntimeException("No Link found for \"" + linkText + "\" with index " + index); } link.click(); } public void clickLinkWithExactText(String linkText, int index) { WebElement link = getLinkWithExactText(linkText, index); if (link == null) { throw new RuntimeException("No Link found for \"" + linkText + "\" with index " + index); } link.click(); } public void clickLink(String anID) { driver.findElement(By.xpath("//a[@id='" + anID + "']")).click(); } public void clickLinkWithImage(String imageFileName, int index) { WebElement link = getLinkWithImage(imageFileName, index); if (link == null) { throw new RuntimeException("No Link found with filename \"" + imageFileName + "\" and index " + index); } link.click(); } public boolean hasElement(String anID) { try { driver.findElement(By.id(anID)); return true; } catch (NoSuchElementException e) { return false; } } public boolean hasElementByXPath(String xpath) { try { driver.findElement(By.xpath(xpath)); return true; } catch (NoSuchElementException e) { return false; } } public void clickElementByXPath(String xpath) { driver.findElement(By.xpath(xpath)).click(); } public String getElementAttributByXPath(String xpath, String attribut) { return driver.findElement(By.xpath(xpath)).getAttribute(attribut); } public String getElementTextByXPath(String xpath) { return driver.findElement(By.xpath(xpath)).getText(); } public boolean isTextInElement(String elementID, String text) { return isTextInElement(driver.findElement(By.id(elementID)), text); } /** * Return true if a given string is contained within the specified element. * * @param element element to inspect. * @param text text to check for. */ private boolean isTextInElement(WebElement element, String text) { return element.getText().indexOf(text) >= 0; } public boolean isMatchInElement(String elementID, String regexp) { return isMatchInElement(driver.findElement(By.id(elementID)), regexp); } /** * Return true if a given regexp is contained within the specified element. * * @param element element to inspect. * @param regexp regexp to match. */ private boolean isMatchInElement(WebElement element, String regexp) { RE re = getRE(regexp); return re.match(element.getText()); } private RE getRE(String regexp) { try { return new RE(regexp, RE.MATCH_SINGLELINE); } catch (RESyntaxException e) { throw new RuntimeException(e); } } public void setExpectedJavaScriptAlert(JavascriptAlert[] alerts) throws ExpectedJavascriptAlertException { throw new UnsupportedOperationException("Not supported yet."); } public void setExpectedJavaScriptConfirm(JavascriptConfirm[] confirms) throws ExpectedJavascriptConfirmException { throw new UnsupportedOperationException("Not supported yet."); } public void setExpectedJavaScriptPrompt(JavascriptPrompt[] prompts) throws ExpectedJavascriptPromptException { throw new UnsupportedOperationException("Not supported yet."); } public IElement getElementByXPath(String xpath) { try { return new WebDriverElementImpl(driver, driver.findElement(By.xpath(xpath))); } catch (NoSuchElementException e) { return null; } } public IElement getElementByID(String id) { try { return new WebDriverElementImpl(driver, driver.findElement(By.id(id))); } catch (NoSuchElementException e) { return null; } } public List<IElement> getElementsByXPath(String xpath) { List<IElement> result = new ArrayList<IElement>(); List<WebElement> elements = driver.findElements(By.xpath(xpath)); for (WebElement child : elements) { result.add(new WebDriverElementImpl(driver, child)); } return result; } public int getServerResponseCode() { return response.getRawResponse().getStatusLine().getStatusCode(); } public String getHeader(String name) { return response.getHeader(name); } public Map<String, String> getAllHeaders() { Map<String, String> map = new java.util.HashMap<String, String>(); for (Header header : response.getRawResponse().getAllHeaders()) { map.put(header.getName(), header.getValue()); } return map; } public void setIgnoreFailingStatusCodes(boolean ignore) { this.ignoreFailingStatusCodes = ignore; } public List<String> getComments() { throw new UnsupportedOperationException("Not supported yet."); } public void setTimeout(int milliseconds) { throw new UnsupportedOperationException("Not supported yet."); } public List<HttpHeader> getResponseHeaders() { List<HttpHeader> result = new LinkedList<HttpHeader>(); for (Header header : response.getRawResponse().getAllHeaders()) { result.add(new HttpHeader(header.getName(), header.getValue())); } return result; } /** * Copied from {@link Select} * @param toEscape * @return */ protected String escapeQuotes(String toEscape) { // Convert strings with both quotes and ticks into: foo'"bar -> concat("foo'", '"', "bar") if (toEscape.indexOf("\"") > -1 && toEscape.indexOf("'") > -1) { boolean quoteIsLast = false; if (toEscape.indexOf("\"") == toEscape.length() - 1) { quoteIsLast = true; } String[] substrings = toEscape.split("\""); StringBuilder quoted = new StringBuilder("concat("); for (int i = 0; i < substrings.length; i++) { quoted.append("\"").append(substrings[i]).append("\""); quoted.append(((i == substrings.length - 1) ? (quoteIsLast ? ", '\"')" : ")") : ", '\"', ")); } return quoted.toString(); } // Escape string with just a quote into being single quoted: f"oo -> 'f"oo' if (toEscape.indexOf("\"") > -1) { return String.format("'%s'", toEscape); } // Otherwise return the quoted string return String.format("\"%s\"", toEscape); } }