org.testeditor.fixture.web.WebFixture.java Source code

Java tutorial

Introduction

Here is the source code for org.testeditor.fixture.web.WebFixture.java

Source

/*******************************************************************************
 * Copyright (c) 2012 - 2015 Signal Iduna Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * Signal Iduna Corporation - initial API and implementation
 * akquinet AG
 *******************************************************************************/

package org.testeditor.fixture.web;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.List;

import org.apache.log4j.Logger;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.Select;
import org.testeditor.fixture.core.elementlist.ElementListService;
import org.testeditor.fixture.core.exceptions.ElementKeyNotFoundException;
import org.testeditor.fixture.core.exceptions.StopTestException;
import org.testeditor.fixture.core.interaction.Fixture;
import org.testeditor.fixture.core.interaction.StoppableFixture;
import org.testeditor.fixture.core.utils.ExceptionUtils;
import org.testeditor.fixture.core.utils.StringUtils;

/**
 * Provides methods for basic Web GUI-testing like click on type input. Projects
 * may inherit from this generic fixture and could use the protected methods for
 * any extensions.
 */
public class WebFixture implements StoppableFixture, Fixture {
    protected static final String LINUX = "Linux";
    protected static final String MAC_OS = "Mac OS";
    protected static final String WINDOWS = "Windows";
    private static final Logger LOGGER = Logger.getLogger(WebFixture.class);

    private Integer waitInMillis = 250;
    private Integer waitCounter = 100;

    private ElementListService elementListService;
    protected WebDriver webDriver;
    private int timeout;

    /**
     * Creates the element list instance representing the GUI-Map for widget
     * element id's of an application and the user defined names for this
     * represented GUI element. Often used in a FitNesse ScenarioLibrary for
     * configuration purpose. <br />
     * 
     * FitNesse usage..: |set elementlist|arg1| <br/>
     * FitNesse example: |set elementlist|../ElementList/content.txt| <br />
     * <br />
     * 
     * @param elementList
     *            relative path of the element list content.txt wiki site on a
     *            FitNesse Server where WikiPages is the directory where all the
     *            Wiki Sites of the recent project are
     */
    public void setElementlist(String elementList) {
        elementListService = ElementListService.instanceFor(elementList);
    }

    /**
     * @return the elementListService
     */
    protected ElementListService getElementlist() {
        return elementListService;
    }

    /**
     * @return the webDriver
     */
    protected WebDriver getWebDriver() {
        return webDriver;
    }

    /**
     * The value is used by the Method waitForElement.
     * 
     * @param waitInMillis
     *            the waitInMillis to set
     */
    public void setWaitInMillis(Integer waitInMillis) {
        this.waitInMillis = waitInMillis;
    }

    /**
     * @return the waitInMillis as an {@link Integer}
     */
    protected Integer getWaitInMillis() {
        return waitInMillis;
    }

    /**
     * The value is used by the Method waitForElement.
     * 
     * @param waitCounter
     *            the waitCounter to set
     */
    public void setWaitCounter(Integer waitCounter) {
        this.waitCounter = waitCounter;
    }

    /**
     * @return the waitCounter
     */
    protected Integer getWaitCounter() {
        return waitCounter;
    }

    /**
     * Opens a specific browser (e.g. Firefox, Google-Chrome or Microsoft
     * Internet Explorer), it is possible to use 'firefox', 'chrome' or 'ie' as
     * the browserName. <br />
     * 
     * FitNesse usage..: |open Browser|arg1| <br />
     * FitNesse example: |open Browser|firefox| <br />
     * <br />
     * 
     * Please note that for Firefox there is a system property
     * 'webdriver.firefox.bin' which should be set to the path of the used
     * browser.
     * 
     * @param browserName
     *            name of browser ('ie', 'chrome' or 'firefox')
     * @param browserPath
     *            path to the browser
     * @return true, if browser starts successful, otherwise false
     */
    public boolean openBrowser(String browserName, String browserPath) {

        String osName = System.getProperty("os.name");
        LOGGER.debug("open browser IN PROCESS - operating System: " + osName + ", browserName: " + browserName);

        try {

            if ("firefox".equalsIgnoreCase(browserName)) {
                openFirefox(osName, browserPath);
            } else if ("ie".equalsIgnoreCase(browserName)) {
                DesiredCapabilities cap = DesiredCapabilities.internetExplorer();
                cap.setCapability(CapabilityType.TAKES_SCREENSHOT, false);
                cap.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, "true");
                webDriver = new InternetExplorerDriver(cap);
            } else if ("chrome".equalsIgnoreCase(browserName)) {
                System.setProperty("webdriver.chrome.driver", browserPath);
                webDriver = new ChromeDriver();
            } else {
                String logMessage = "browser '" + browserName + " not available";
                LOGGER.error(logMessage);
                throw new StopTestException(logMessage);
            }

        } catch (WebDriverException e) {
            // here will be thrown an exception if installed browser was not
            // found
            LOGGER.error(e.getMessage(), e);
            throw new StopTestException(e.getMessage());
        }

        return true;
    }

    /**
     * Helper method for openBrowser which handles the specifics to open
     * Firefox.
     * 
     * @param osName
     *            the name of the OS (should contain "Windows", "Mac OS" or
     *            "Linux")
     * @param browserPath
     *            path to the (portable) Firefox executable to be started
     */
    private void openFirefox(String osName, String browserPath) {

        try {
            if (browserPath != null && !browserPath.equals("")) {

                if (osName.contains(WINDOWS)) {
                    System.setProperty("webdriver.firefox.bin", browserPath);
                } else if (osName.contains(LINUX)) {
                    System.setProperty("webdriver.firefox.bin", browserPath);
                    System.setProperty("webdriver.firefox.profile", "testing");

                } else if (osName.contains(MAC_OS)) {
                    System.setProperty("webdriver.firefox.bin", browserPath);
                }

                // check if given browser path exists
                // and throw an exception if not exists
                if (!(new File(browserPath)).exists()) {
                    String logMessage = "browserPath '" + browserPath + " does not exist";
                    LOGGER.error(logMessage);
                    throw new StopTestException(logMessage);
                }
            }

            webDriver = new FirefoxDriver();
        } catch (WebDriverException e) {
            // here will be thrown an exception if installed browser was not
            // found
            LOGGER.error(e.getMessage(), e);
            throw new StopTestException(e.getMessage());
        }
    }

    /**
     * Navigates to a new web page in the current browser window. <br />
     * 
     * Usage for FitNesse: |navigate to Url|http://www.example.org|<br />
     * 
     * FitNesse usage..: |navigate to Url|arg1| <br />
     * FitNesse example: |navigate to Url|http://www.example.org| <br />
     * <br />
     * 
     * @param url
     *            URL of page to navigate to
     * @return always true to show inside FitNesse a positive result
     */
    public boolean navigateToUrl(String url) {
        webDriver.get(url);
        return true;
    }

    /**
     * Checks if a given value is empty (i.e. a <code>null</code>-value or an
     * empty string.
     * 
     * FitNesse usage..: |assert|arg1|is empty| <br />
     * FitNesse example: |assert|Some Text|is empty| <br />
     * <br />
     * 
     * @param value
     *            the value to compare
     * @return <code>true</code> if <code>value</code> is an empty string,
     *         <code>false</code> otherwise
     */
    public boolean assertIsEmpty(String value) {
        boolean result = false;
        if (value == null || value.trim().isEmpty()) {
            result = true;
        }
        return result;
    }

    /**
     * Checks if a given value is not empty (i.e. not a <code>null</code>-value
     * or an empty string.
     * 
     * FitNesse usage..: |assert|arg1|is not empty| <br />
     * FitNesse example: |assert|Some Text|is not empty| <br />
     * <br />
     * 
     * @param value
     *            the value to compare
     * @return <code>true</code> if <code>value</code> is not an empty string,
     *         <code>false</code> otherwise
     */
    public boolean assertIsNotEmpty(String value) {
        return !assertIsEmpty(value);
    }

    /**
     * Compares a given value with another value for equality.
     * 
     * FitNesse usage..: |assert|arg1|is equal to|arg2| <br />
     * FitNesse example: |assert|Some Text|is equal to|Some Other Text| <br />
     * <br />
     * 
     * @param first
     *            the first value to compare
     * @param second
     *            the second value to compare
     * @return <code>true</code> if <code>first</code> is equal to
     *         <code>second</code>, <code>false</code> otherwise
     */
    public boolean assertIsEqualTo(String first, String second) {
        boolean result = false;

        if (first == null && second == null) {
            result = true;
        } else if (first != null && second != null && (first.trim()).equals(second.trim())) {
            result = true;
        }

        return result;
    }

    /**
     * Compares a given value with another value for inequality.
     * 
     * FitNesse usage..: |assert|arg1|is not equal to|arg2| <br />
     * FitNesse example: |assert|Some Text|is not equal to|Some Other Text|
     * <br />
     * <br />
     * 
     * @param first
     *            the first value to compare
     * @param second
     *            the second value to compare
     * @return <code>true</code> if <code>first</code> is not equal to
     *         <code>second</code>, <code>false</code> otherwise
     */
    public boolean assertIsNotEqualTo(String first, String second) {
        return !assertIsEqualTo(first, second);
    }

    /**
     * Checks if a given string is found within another string.
     * 
     * FitNesse usage..: |assert|arg1|contains|arg2| <br />
     * FitNesse example: |assert|Some Text|contains|me Te| <br />
     * <br />
     * 
     * @param first
     *            the string to analyze
     * @param second
     *            the string to be found within <code>first</code>
     * @return <code>true</code> if <code>first</code> contains
     *         <code>second</code>, <code>false</code> otherwise
     */
    public boolean assertContains(String first, String second) {
        boolean result = false;

        if (first == null && second == null) {
            result = true;
        } else if (first != null && second != null && first.contains(second.trim())) {
            result = true;
        }

        return result;
    }

    /**
     * Searches elements using XPath from the element list. This test asserts,
     * that the XPath query yields at least one hit.<br />
     * <br />
     * 
     * FitNesse usage..: |assert element|arg1|found|[arg2, arg3, ...]| <br />
     * FitNesse example: |assert element|TextboxInRow{0}Col{1}|found|[5, 3]|
     * <br />
     * <br />
     * 
     * @param elementListKey
     *            key to find the technical locator
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return true, if at least one element matches the XPath query; false
     *         otherwise.
     */
    public boolean assertElementFound(String elementListKey, String... replaceArgs) {
        boolean result = false;

        WebElement element = findWebelement(elementListKey, replaceArgs);

        if (element != null) {
            result = true;
        }

        return result;
    }

    /**
     * Searches elements by key from the element list. This method asserts, that
     * the element does not exists.
     * 
     * FitNesse usage..: |assert element|arg1|not found|[arg2, arg3, ...]|
     * <br />
     * FitNesse example: |assert element|TextboxInRow{0}Col{1}|not found|[5, 3]|
     * <br />
     * <br />
     * 
     * @param elementListKey
     *            key to find the technical locator
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return true, if no elements with the given key exists; false otherwise.
     */
    public boolean assertElementNotFound(String elementListKey, String... replaceArgs) {
        boolean result = false;
        Integer waitCounterOriginalValue = waitCounter;

        // If the target element cannot be found, don't wait too.
        waitCounter = 2;
        try {
            // If no exception is thrown, then the target element was found...
            WebElement element = findWebelement(elementListKey, false, replaceArgs);
            if (element == null) {
                result = true;
            }
        } catch (TimeoutException e) {
            // Search for the target element timed out, which is exactly what we
            // wanted. In this case the exception will be silently discarded and
            // the result of this method is true.
            result = true;
        }
        // Restore the original timeout wait counter.
        waitCounter = waitCounterOriginalValue;

        return result;
    }

    /**
     * Finds an element on the web page by its Element List key and inputs a
     * special key stroke in its context. <br />
     * <br />
     * 
     * FitNesse usage..: |enter special key|arg1| <br />
     * FitNesse example: |enter special key|RIGHT| <br />
     * <br />
     * 
     * @param key
     *            the key stroke to enter (see
     *            https://code.google.com/p/selenium
     *            /source/browse/java/client/src/org/openqa/selenium/Keys.java)
     * @return the value of the target element; empty String, if the element
     *         could not be found or is not visible (i.e. hidden using CSS,
     *         etc.).
     */
    public boolean enterSpecialKey(String key) {
        boolean result = false;

        Keys seleniumKey = Keys.NULL;
        try {
            seleniumKey = Keys.valueOf(key.toUpperCase());
        } catch (IllegalArgumentException e) {
            String message = "The specified key \"" + key
                    + "\" is invalid and could not be found in selenium enum Keys!";
            LOGGER.error(message, e);
            throw new StopTestException(message);
        }

        Actions action = new Actions(webDriver);
        action.sendKeys(seleniumKey).build().perform();
        result = true;

        return result;
    }

    /**
     * Finds a textbox by its Element List key and gets its value. <br />
     * <br />
     * 
     * FitNesse usage..: |$var=|read textbox;|arg1|[arg2, arg3, ...]| <br />
     * FitNesse example: |$result=|read textbox;|TextboxInRow{0}Col{1}|[5, 3]|
     * <br />
     * <br />
     * 
     * @param elementListKey
     *            key to find the technical locator
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return the value of the target element; empty String, if the element
     *         could not be found or is not visible (i.e. hidden using CSS,
     *         etc.).
     */
    public String readTextbox(String elementListKey, String... replaceArgs) {
        return readAttributeFromField("value", elementListKey, replaceArgs);
    }

    /**
     * Finds a combobox by its Element List key and gets its value. <br />
     * <br />
     * 
     * FitNesse usage..: |$var=|read combobox;|arg1|[arg2, arg3, ...]| <br />
     * FitNesse example: |$result=|read combobox;|ComboboxInRow{0}Col{1}|[5, 3]|
     * <br />
     * <br />
     * 
     * @param elementListKey
     *            key to find the technical locator
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return the value of the target element; empty String, if the element
     *         could not be found or is not visible (i.e. hidden using CSS,
     *         etc.).
     */
    public String readCombobox(String elementListKey, String... replaceArgs) {
        return readAttributeFromField("value", elementListKey, replaceArgs);
    }

    /**
     * Finds a checkbox by its Element List key and gets its value. <br />
     * <br />
     * 
     * FitNesse usage..: |$var=|read checkbox;|arg1|[arg2, arg3, ...]| <br />
     * FitNesse example: |$result=|read checkbox;|CheckboxInRow{0}Col{1}|[5, 3]|
     * <br />
     * <br />
     * 
     * @param elementListKey
     *            key to find the technical locator
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return true, if the target element is checked; false, if the element is
     *         not checked or the element could not be found or is not visible
     *         (i.e. hidden using CSS, etc.).
     */
    public boolean readCheckbox(String elementListKey, String... replaceArgs) {
        boolean result = false;

        WebElement element = findWebelement(elementListKey, replaceArgs);

        if (element != null && element.isDisplayed()) {
            result = element.isSelected();
        }

        return result;
    }

    /**
     * Finds an element by its Element List key and gets the value of an
     * associated attribute (e.g. <code>"value"</code> or
     * <code>"innerText"</code> ). <br />
     * <br />
     * 
     * FitNesse usage..: |$var=|read attribute|arg1|from field;|arg2|[arg3,
     * arg4, ...]| <br />
     * FitNesse example: |$result=|read attribute|value|from
     * field;|CheckboxInRow{0}Col{1}|[5, 3]| <br />
     * <br />
     * 
     * @param attribute
     *            the attribute to get from the target element
     * @param elementListKey
     *            key to find the technical locator
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return the value associated with the given <code>attribute</code> of the
     *         target element; empty String, if the element could not be found
     *         or is not visible (i.e. hidden using CSS, etc.).
     */
    public String readAttributeFromField(String attribute, String elementListKey, String... replaceArgs) {
        String result = privateReadAttributeFromField(attribute, elementListKey, replaceArgs);

        return result;
    }

    /**
     * 
     * @param attribute
     *            the attribute to get from the target element
     * @param elementListKey
     *            key to find the technical locator
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return the value associated with the given <code>attribute</code> of the
     *         target element; empty String, if the element could not be found
     *         or is not visible (i.e. hidden using CSS, etc.).
     */
    private String privateReadAttributeFromField(String attribute, String elementListKey, String... replaceArgs) {
        String result = "";

        WebElement element = findWebelement(elementListKey, replaceArgs);

        if (element != null && element.isDisplayed()) {
            if (attribute.equalsIgnoreCase("innertext")) {
                result = element.getText();
            } else {
                result = element.getAttribute(attribute);
            }
        }
        return result;
    }

    /**
     * Inserts the given value into an input field and checks if input was
     * successful. The technical locator of the field gets identified by the
     * element list matching the given key. <br />
     * 
     * FitNesse usage..: |insert|arg1|into field;|arg2|[arg3, arg4, ...]| <br />
     * FitNesse example: |insert|Some Text|into field;|TextboxInRow{0}Col{1}|[5,
     * 3]| <br />
     * <br />
     * 
     * @param elementListKey
     *            key to find the technical locator
     * @param value
     *            value for the input
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return true if input was successful, otherwise false
     */
    public void insertIntoField(String value, String elementListKey, String... replaceArgs) {

        WebElement element = findWebelement(elementListKey, replaceArgs);

        if (element != null && element.isDisplayed()) {
            element.click();
            element.sendKeys(value);
            String expectedValue = null;
            if (element.getTagName().equalsIgnoreCase("select")) {
                Select s = new Select(element);
                expectedValue = s.getFirstSelectedOption().getText();
            } else {
                expectedValue = readAttributeFromField("value", elementListKey, replaceArgs);
            }

            if (!assertIsEqualTo(value, expectedValue)) {
                throw new StopTestException("Value wasn't inserted correctly");
            }
        }

    }

    /**
     * Works just like
     * <code>insertIntoField(value, elementListKey, replaceArgs)</code> except
     * the argument <code>replaceArgs</code> is always an empty array.
     * 
     * @param elementListKey
     *            key to find the technical locator
     * @param value
     *            value for the input
     * @return true if input was successful, otherwise false
     */
    public void insertIntoField(String value, String elementListKey) {
        insertIntoField(value, elementListKey, new String[] {});
    }

    /**
     * Clears a given input field. The technical locator of the field gets
     * identified by the element list matching the given key.<br />
     * 
     * FitNesse usage..: |clear;|arg1|[arg2, arg3, ...]| <br />
     * FitNesse example: |clear;|TextboxInRow{0}Col{1}|[5, 3]| <br />
     * <br />
     * 
     * @param elementListKey
     *            key to find the technical locator
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return true if clear was successful, otherwise false
     */
    public boolean clear(String elementListKey, String... replaceArgs) {
        boolean result = false;

        WebElement element = findWebelement(elementListKey, replaceArgs);

        if (element != null && element.isDisplayed()) {
            element.clear();
            result = true;
        }

        return result;
    }

    /**
     * Works just like <code>clear(elementListKey, replaceArgs)</code> except
     * the argument <code>replaceArgs</code> is always an empty array.
     * 
     * @param elementListKey
     *            key to find the technical locator
     * @return true if clear was successful, otherwise false
     */
    public boolean clear(String elementListKey) {
        return clear(elementListKey, new String[] {});
    }

    /**
     * Checks if a given input field is enabled (i.e. editable). The technical
     * locator of the field gets identified by the element list matching the
     * given key.<br />
     * 
     * FitNesse usage..: |assert element|arg1|enabled|[arg2, arg3, ...]| <br />
     * FitNesse example: |assert element|TextboxInRow{0}Col{1}|enabled|[5, 3]|
     * <br />
     * <br />
     * 
     * @param elementListKey
     *            key to find the technical locator
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return true if the field is enabled, otherwise false
     */
    public boolean assertElementEnabled(String elementListKey, String... replaceArgs) {
        boolean result = false;

        WebElement element = findWebelement(elementListKey, replaceArgs);

        if (element != null && element.isDisplayed() && element.isEnabled()) {
            result = true;
        }

        return result;
    }

    /**
     * Checks if a given input field is not enabled (i.e. not editable). The
     * technical locator of the field gets identified by the element list
     * matching the given key.<br />
     * 
     * FitNesse usage..: |assert element|arg1|disabled|[arg2, arg3, ...]| <br />
     * FitNesse example: |assert element|TextboxInRow{0}Col{1}|disabled|[5, 3]|
     * <br />
     * <br />
     * 
     * @param elementListKey
     *            key to find the technical locator
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return true if the field is not enabled, otherwise false
     */
    public boolean assertElementDisabled(String elementListKey, String... replaceArgs) {
        return !assertElementEnabled(elementListKey, replaceArgs);
    }

    /**
     * Waits for the given period of time before executing the next command.
     * <br />
     * 
     * FitNesse usage..: |wait seconds|arg1| <br />
     * FitNesse example: |wait seconds|2| <br />
     * <br />
     * 
     * @param timeToWait
     *            Time to wait in seconds
     * @return always true to show inside FitNesse a positive result
     */
    public boolean waitSeconds(long timeToWait) {
        waitTime(timeToWait * 1000);
        return true;
    }

    /**
     * Waits for the given period.
     * 
     * @param milliseconds
     *            Time to wait in milliseconds
     */
    protected void waitTime(long milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (InterruptedException e) {
            LOGGER.error(e.getMessage());
        }
    }

    /**
     * Clicks on a element or button. <br />
     * <br />
     * 
     * FitNesse usage..: |click;|arg1|[arg2, arg3, ...]| <br />
     * FitNesse example: |click;|ButtonInRow{0}Col{1}|[5, 3]| <br />
     * <br />
     * 
     * @param elementListKey
     *            key to find the technical locator
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return true if click was successful; otherwise false
     */
    public void click(String elementListKey, String... replaceArgs) {

        WebElement element = findWebelement(elementListKey, replaceArgs);

        if (element != null && element.isDisplayed()) {
            element.click();
        }

    }

    /**
     * Works just like <code>click(elementListKey, replaceArgs)</code> except
     * the argument <code>replaceArgs</code> is always an empty array.
     * 
     * @param elementListKey
     *            key to find the technical locator
     * @return true if click was successful; otherwise false
     */
    public void click(String elementListKey) {
        click(elementListKey, new String[] {});
    }

    /**
     * Double clicks on a element or button. <br />
     * <br />
     * 
     * FitNesse usage..: |double click;|arg1|[arg2, arg3, ...]| <br />
     * FitNesse example: |double click;|ButtonInRow{0}Col{1}|[5, 3]| <br />
     * <br />
     * 
     * @param elementListKey
     *            key to find the technical locator
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return true if click was successful; otherwise false
     */
    public boolean doubleClick(String elementListKey, String... replaceArgs) {
        boolean result = false;

        WebElement element = findWebelement(elementListKey, replaceArgs);

        if (element != null && element.isDisplayed()) {
            Actions action = new Actions(webDriver);
            action.doubleClick(element).build().perform();
            result = true;
        }

        return result;
    }

    /**
     * Searches for a given text in the HTML source and returns true if found.
     * If the text is not found immediately, this method will retry for as long
     * as this class would normally also wait for a widget to found.
     * 
     * FitNesse usage..: |wait for text|arg1| <br />
     * FitNesse example: |wait for text|Login successful| <br />
     * <br />
     * 
     * @param text
     *            to be searched for
     * @return true if the String-Value of <code>text</code> is present; throws
     *         a StopTestException otherwise.
     */
    public boolean waitForText(String text) {
        boolean result = false;
        int counter = 0;

        while (counter < waitCounter) {
            result = webDriver.getPageSource().contains(text);
            if (result) {
                break;
            }

            waitTime(waitInMillis);
            counter++;
        }

        if (!result) {
            String message = "The specified text \"" + text + "\" could not be found!";
            LOGGER.error(message);
            throw new StopTestException(message);
        }

        return result;
    }

    /**
     * Searches for a given text in the HTML source and returns true if found.
     * 
     * FitNesse usage..: |text|arg1|is visible| <br />
     * FitNesse example: |text|Login successful|is visible| <br />
     * <br />
     * 
     * @param text
     *            to be searched for
     * @return true if the String-Value of <code>text</code> is present, false
     *         otherwise
     */
    public boolean textIsVisible(String text) {
        boolean result = webDriver.getPageSource().contains(text);
        if (!result) {
            String message = "The specified text \"" + text + "\" could not be found!";
            LOGGER.error(message);
        }

        return result;
    }

    /**
     * Searches for a given text in the HTML source and returns true if found.
     * 
     * FitNesse usage..: |text|arg1|is visible| <br />
     * FitNesse example: |text|Login successful|is visible| <br />
     * <br />
     * 
     * @param text
     *            to be searched for
     * @param elementListKey
     *            key to find the technical locator
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return true if the String-Value of <code>text</code> is present, false
     *         otherwise
     */
    public boolean textIsVisibleInField(String text, String elementListKey, String... replaceArgs) {
        String result = privateReadAttributeFromField("innertext", elementListKey, replaceArgs);
        return result.equalsIgnoreCase(text);
    }

    /**
     * Switches to another frame (e.g. iFrame).
     * 
     * @param elementListKey
     *            key to find the technical locator
     * @return true if switch successed
     */
    public boolean switchToFrame(String elementListKey) {
        WebElement webElement = findWebelement(elementListKey);
        webDriver.switchTo().frame(webElement);

        return true;
    }

    /**
     * Searches for a given text in the HTML source and returns true if not
     * found.
     * 
     * FitNesse usage..: |text|arg1|is unvisible| <br />
     * FitNesse example: |text|Login successful|is unvisible| <br />
     * <br />
     * 
     * @param text
     *            to be searched for
     * @return true if the String-Value of <code>text</code> isn't present,
     *         false otherwise
     */
    public boolean textIsUnvisible(String text) {
        boolean result = !webDriver.getPageSource().contains(text);
        if (!result) {
            String message = "The specified text \"" + text + "\" could be found!";
            LOGGER.error(message);
        }

        return result;
    }

    /**
     * Close the browser instance.
     * 
     * FitNesse usage..: |close browser| <br />
     * FitNesse example: |close browser| <br />
     * <br />
     * 
     * @return always true to show inside FitNesse a positive result
     */
    public boolean closeBrowser() {
        // checks if Browser is Chrome because Chromedriver does not function
        // with Close-Method of WebDriver
        if (webDriver instanceof ChromeDriver) {
            webDriver.quit();
        } else {
            webDriver.close();
            // necessary wait, at least for FF portable
            waitTime(500);
            // best effort
            try {
                webDriver.quit();
                // CHECKSTYLE:OFF
            } catch (Throwable t) { // disable checkstyle for empty block
                // CHECKSTYLE:ON
                // NFA - at least Firefox portable is down after close()
            }
        }
        return true;
    }

    /**
     * Simulates a MouseOver on a Menu. Moves to the given Gui-Element.
     * 
     * FitNesse usage..: |move to element;|arg1|[arg2, arg3, ...]| <br />
     * FitNesse example: |move to element;|IconInRow{0}Col{1}|[5, 3]| <br />
     * <br />
     * 
     * @param elementListKey
     *            the Gui-Element where to move.
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return true if WebElement is found and Mouse moved to this Element to
     *         perform an Action.
     */
    public boolean moveToElement(String elementListKey, String... replaceArgs) {
        boolean result = false;

        WebElement element = findWebelement(elementListKey, replaceArgs);

        if (element != null && element.isDisplayed()) {

            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("element found ready for Action (moveToElement)");
            }
            Actions actions = new Actions(webDriver);
            actions.moveToElement(element).build().perform();
            result = true;
        }

        return result;
    }

    /**
     * Move to element and click menu.
     * 
     * @param elementListKey
     *            key of element in elementList.conf.
     * @param menuEntryKey
     *            key of menu.
     * @return true if element is found and menu is activated.
     */
    public void moveToElementAndClickMenu(String elementListKey, String menuEntryKey) {

        WebElement element = findWebelement(elementListKey, new String[] {});

        if (element != null && element.isDisplayed()) {

            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("element found ready for Action (moveToElement)");
            }
            Actions actions = new Actions(webDriver);
            actions.moveToElement(element).build().perform();
        }
        click(menuEntryKey);

    }

    /**
     * Works just like <code>moveToElement(elementListKey, replaceArgs)</code>
     * except the argument <code>replaceArgs</code> is always an empty array.
     * 
     * @param elementListKey
     *            the Gui-Element where to move.
     * @return true if WebElement is found and Mouse moved to this Element to
     *         perform an Action.
     */
    public boolean moveToElement(String elementListKey) {
        return moveToElement(elementListKey, new String[] {});
    }

    /**
     * This Method finds WebElements with a given Key as XPATH expression or
     * id-value.
     * 
     * @param elementListKey
     *            key in the ElementList
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return the webElement if element is not found, then return null
     */
    protected WebElement findWebelement(String elementListKey, String... replaceArgs) {
        return findWebelement(elementListKey, true, replaceArgs);
    }

    /**
     * This Method finds WebElements with a given Key as XPATH expression or
     * id-value.
     * 
     * @param elementListKey
     *            key in the ElementList
     * @param handleTimeout
     *            specifies if a TimeoutException should be handled by this
     *            method (default: true!) or in special cases (e.g.
     *            assertElementNotFound) should be handled by the calling method
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return the webElement if element is not found, then return null
     */
    protected WebElement findWebelement(String elementListKey, boolean handleTimeout, String... replaceArgs) {
        WebElement element = null;

        try {
            element = waitForElement(createByFromElementList(elementListKey, replaceArgs));
        } catch (TimeoutException e) {
            if (handleTimeout) {
                LOGGER.error(elementListKey);
                LOGGER.error(e.getMessage());
                ExceptionUtils.handleNoSuchElementException(elementListKey, e);
            } else {
                // Don't handle the exception here. Just pass it on to the
                // caller. For instance, when the caller expects that finding a
                // certain element will fail.
                throw e;
            }
        }

        return element;
    }

    /**
     * Wait for a element with a given Key as XPATH expression or id-value.
     * 
     * @param elementListKey
     *            key in the ElementList
     * @return true if WebElement is found and displayed
     */
    public boolean waitForElement(String elementListKey) {
        boolean result = false;

        WebElement element = findWebelement(elementListKey);
        if (element != null && element.isDisplayed()) {
            result = true;
        }
        return result;
    }

    /**
     * This Method finds WebElements with a given {@link By}. If the given
     * {@link By} is an XPath expression and matches multiple elements, this
     * method will return the first visible element (as determined by selenium's
     * {@link isDisplayed} method) that matches.
     * 
     * @param context
     *            the search context or subtree to query. Argument
     *            <code>context</code> may be <code>null</code> to search the
     *            whole document.
     * @param by
     *            Mechanism used to locate elements within a document
     * @return the webElement
     * @throws TimeoutException
     *             if element is not found
     */
    protected WebElement waitForElement(final WebElement context, final By by) throws TimeoutException {
        List<WebElement> elements = null;
        WebElement result = null;
        int counter = 0;

        while (elements == null) {
            if (counter >= waitCounter) {
                break;
            }

            try {
                if (context == null) {
                    elements = webDriver.findElements(by);
                } else {
                    elements = context.findElements(by);
                }
            } catch (Exception e) {
                elements = null;
            }

            if (elements != null) {
                result = getFirstDisplayed(elements);
                if (result != null) {
                    break;
                }
            }

            elements = null;
            waitTime(waitInMillis);
            counter++;
        }

        if (result == null || !result.isDisplayed()) {
            throw new TimeoutException("Timeout: no element was found");
        }

        return result;
    }

    /**
     * Iterates over a list of web elements and returns the first that is
     * visible (as determined by selenium's {@link isDisplayed} method).
     * 
     * @param elements
     *            the element list to search
     * @return the first visible element from the supplied list; null if the
     *         list is empty or not web element is visible
     */
    private WebElement getFirstDisplayed(List<WebElement> elements) {
        WebElement result = null;
        if (elements != null) {
            for (WebElement element : elements) {
                if (element.isDisplayed()) {
                    result = element;
                    break;
                }
            }
        }
        return result;
    }

    /**
     * This Method finds WebElements with a given {@link By}.
     * 
     * @param by
     *            Mechanism used to locate elements within a document
     * @return the webElement
     * @throws TimeoutException
     *             if element is not found
     */
    protected WebElement waitForElement(final By by) throws TimeoutException {
        return waitForElement(null, by);
    }

    /**
     * Returns the locator for a given key.
     * 
     * @param elementListKey
     *            key in the ElementList
     * @return locator as String
     */
    protected String getLocatorFromElementList(String elementListKey) {

        try {
            return elementListService.getValue(elementListKey);
        } catch (ElementKeyNotFoundException e) {
            return defaultHandelKeyNotFoundException(elementListKey, e);
        }

    }

    /**
     * 
     * @param elementListKey
     *            key in the ElementList, that isn't found.
     * @param e
     *            ElementKeyNotFoundException always thrown
     */
    protected String defaultHandelKeyNotFoundException(String elementListKey, ElementKeyNotFoundException e) {
        ExceptionUtils.handleElementKeyNotFoundException(elementListKey, e);
        return "";
    }

    /**
     * This Method create a By instance with a given Key as XPATH expression or
     * id-value.
     * 
     * @param elementListKey
     *            key (e.g. inputUsername)
     * @param replaceArgs
     *            values to replace the place holders in the element list entry
     *            with
     * @return By
     */
    protected By createByFromElementList(String elementListKey, String... replaceArgs) {
        String locator = getLocatorFromElementList(elementListKey);
        // Apostrophes in X-Paths must not be wiped out - hence escape
        if (locator.contains("%")) {
            LOGGER.info("contains % " + locator);
            locator = createXPathFromLocator(locator);
            LOGGER.info("replaced % " + locator);
        }
        if (locator != null) {
            locator = locator.replace("'", "''");
        }

        Object[] args;
        if (replaceArgs != null) {
            args = replaceArgs;
        } else {
            args = new Object[] {};
        }
        locator = MessageFormat.format(locator, args);

        By by;
        if (hasElementPrefix(locator)) {
            by = getByFromLacatorWithPraefix(locator);
        } else if (StringUtils.isXPath(locator)) {
            by = By.xpath(locator);
        } else {
            by = By.id(locator);
        }
        LOGGER.info(by);
        return by;
    }

    /**
     * 
     * 
     * @param locator
     *            as a String
     * @return true if the locator starts with an ElementPrefix
     */
    protected boolean hasElementPrefix(String locator) {
        return locator.startsWith(ElementPrefix.CLASSNAME.getName())
                || locator.startsWith(ElementPrefix.CSSSELECTOR.getName())
                || locator.startsWith(ElementPrefix.ID.getName())
                || locator.startsWith(ElementPrefix.LINKTEXT.getName())
                || locator.startsWith(ElementPrefix.NAME.getName())
                || locator.startsWith(ElementPrefix.PARTIAL.getName())
                || locator.startsWith(ElementPrefix.TAGNAME.getName())
                || locator.startsWith(ElementPrefix.XPATH.getName());
    }

    /**
     * 
     * @param locator
     *            identified by an element of the {@link ElementPrefix}
     * @return By
     */
    private By getByFromLacatorWithPraefix(String locator) {
        if (locator.startsWith(ElementPrefix.CLASSNAME.getName())) {
            locator = locator.substring(ElementPrefix.CLASSNAME.getName().length());
            return By.className(locator);
        } else if (locator.startsWith(ElementPrefix.CSSSELECTOR.getName())) {
            locator = locator.substring(ElementPrefix.CSSSELECTOR.getName().length());
            return By.cssSelector(locator);
        } else if (locator.startsWith(ElementPrefix.ID.getName())) {
            locator = locator.substring(ElementPrefix.ID.getName().length());
            return By.id(locator);
        } else if (locator.startsWith(ElementPrefix.LINKTEXT.getName())) {
            locator = locator.substring(ElementPrefix.LINKTEXT.getName().length());
            return By.linkText(locator);
        } else if (locator.startsWith(ElementPrefix.NAME.getName())) {
            locator = locator.substring(ElementPrefix.NAME.getName().length());
            return By.name(locator);
        } else if (locator.startsWith(ElementPrefix.PARTIAL.getName())) {
            locator = locator.substring(ElementPrefix.PARTIAL.getName().length());
            return By.partialLinkText(locator);
        } else if (locator.startsWith(ElementPrefix.TAGNAME.getName())) {
            locator = locator.substring(ElementPrefix.TAGNAME.getName().length());
            return By.tagName(locator);
        } else if (locator.startsWith(ElementPrefix.XPATH.getName())) {
            locator = locator.substring(ElementPrefix.XPATH.getName().length());
            return By.xpath(locator);
        }
        return By.id(locator);
    }

    /**
     * 
     * @param locator
     *            the locator including '%'
     * @return the xpath with contains the locator.
     */
    protected String createXPathFromLocator(String locator) {
        String tempLocator = locator.replaceAll("%", "");
        LOGGER.info(tempLocator);
        String lc = "//*[contains(@id,'" + tempLocator + "')]";
        LOGGER.info(lc);
        return lc;

    }

    /**
     * Invalid JavaDoc: Sets the implicit wait timeout in seconds for each test
     * step.<br />
     * 
     * FitNesse usage..: |set timeout|arg1| <br />
     * FitNesse example: |set timeout|1| <br />
     * <br />
     * 
     * @param timeout
     *            timeout in seconds
     */
    public void setTimeout(String timeout) {
        this.timeout = Integer.valueOf(timeout);
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace(">>>> Set timeout to: " + this.timeout + " seconds. <<<<<");
        }
    }

    /**
     * Checks if value is visible and if not stops the test.
     * 
     * @param value
     *            Value to be found on website
     * @return result True if value was found
     */
    public boolean checkTextAndTearDown(String value) {
        boolean result = webDriver.getPageSource().contains(value);
        if (!result) {
            String message = "The specified text \"" + value + "\" could not be found!";
            result = true;
            throw new StopTestException(message, new Throwable());
        }
        return result;
    }

    @Override
    public void tearDown(boolean failure) {
        closeBrowser();
    }

    public String getTestName() {
        return null;
    }

    public void postInvoke(Method arg0, Object arg1, Object... arg2)
            throws InvocationTargetException, IllegalAccessException {
    }

    public void preInvoke(Method arg0, Object arg1, Object... arg2)
            throws InvocationTargetException, IllegalAccessException {
    }

    public void setTestName(String arg0) {
    }
}