app.web.SeleniumPage.java Source code

Java tutorial

Introduction

Here is the source code for app.web.SeleniumPage.java

Source

/*
 * Copyright (C) 2013 Pascal Mazars
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package app.web;

import com.thoughtworks.selenium.Selenium;
import com.thoughtworks.selenium.SeleniumException;
import org.openqa.selenium.internal.seleniumemulation.Open;
import org.springframework.util.StringUtils;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Object-oriented flavoured testing.
 */
public class SeleniumPage implements Page {
    protected Selenium selenium;
    //    protected Stack<URL> locationStack;
    protected Stack<Action> actionStack;
    protected static Page currentPage;
    protected int inputCounter; // Maybe better if we could have tabIndex instead
    protected int selectCounter;// Maybe better if we could have tabIndex instead
    public static final Integer TIMEOUT = 300000;
    public static int PAGE_LOAD_MAX_WAIT = 2000;

    public SeleniumPage(Selenium selenium, final String url) {
        this(selenium, url, new Stack<Action>());
        this.selenium.open(url);
        currentPage = this;
    }

    //    public static SeleniumPage newSeleniumPage(SeleniumPage page, Action action) {
    //        page.getActionStack().push(action);
    //        return new SeleniumPage(page.selenium, page.getActionStack());
    //    }

    //    public SeleniumPage(Selenium selenium, Stack<Action> actionStack) {
    //        this(selenium, actionStack.firstElement().getValue()); //open
    //        for (int i = 1; i < actionStack.size(); i++) {
    //            this.clickAndWaitForLoadIfNecessary(actionStack.get(i).getTarget(), false);
    //        }
    //    }

    /**
     * This method is used internally only.
     * @param selenium seleniumBrowser
     * @param url the new current URL
     * @param actionStack the current action stack (history of past actions)
     */
    private SeleniumPage(Selenium selenium, final String url, Stack<Action> actionStack) {
        this.selenium = selenium;
        this.actionStack = new Stack<Action>();
        if (actionStack.isEmpty()) {
            this.actionStack.push(Action.open(url));
        } else {
            this.actionStack.addAll(actionStack);
            //            this.actionStack.push(Action.navigationNewPage("#target", url));
        }
        currentPage = this;
    }

    public static Page getCurrentPage() {
        return currentPage;
    }

    public boolean isCurrentPage() {
        // Perhaps we need to implement equals/hashCode
        return this.equals(currentPage);
    }

    public void assertIsCurrentPage() {
        if (!isCurrentPage())
            throw new IllegalStateException(this + " is not the current page");
    }

    //    /**
    //     * Merge with click...?
    //     * @param action
    //     * @return
    //     */
    //    @Override
    //    public Page registerAction(Action action) {
    ////        Action previousAction = actionStack.pop();
    ////        if (previousAction.getType() == Action.ActionType.CLICK_DOM_UPDATE) {
    ////            throw new IllegalStateException("previousAction.getType()=" + previousAction.getType());
    ////        }
    //        actionStack.push(action);
    ////        if (action.getType() == Action.ActionType.CLICK_NEW_PAGE || action.getType() == Action.ActionType.CLICK_SAME_PAGE) {
    ////            return new SeleniumPage(selenium, actionStack);
    ////        }
    //        return this;
    //    }

    @Override
    public Stack<Action> getActionStack() {
        return actionStack;
    }

    @Override
    public Stack<URL> getLocationStack() {
        Stack<URL> locationStack = new Stack<URL>();
        for (Action action : actionStack) {
            if (action.getType() == Action.ActionType.OPEN
                    || action.getType() == Action.ActionType.CLICK_NEW_PAGE) {
                locationStack.push(toLocationPath(action.getValue()));
            }
        }
        return locationStack;
    }

    @Override
    public SeleniumPage click(String locator) {
        assertIsCurrentPage();
        assertUniqueElement(locator);
        selenium.click(locator);
        //        if (actionStack == null)
        //            actionStack = new Stack<Action>();
        //        actionStack.push(Action.domUpdate(locator));
        return this;
    }

    @Override
    public Page clickAndWait(String locator) {
        return clickAndWaitForLoadIfNecessary(locator, true);
    }

    //    public Page clickAndWaitForLoadIfNecessary(String locator, boolean forceWaitForLoad) {
    //        click(locator);
    //        return waitForLoadIfNecessary(forceWaitForLoad);
    //    }

    private boolean waitForLoadIfNecessary(boolean forceWaitForLoad) {
        if (forceWaitForLoad) {
            waitForPageToLoad(Integer.toString(PAGE_LOAD_MAX_WAIT));
            //            actionStack.pop(); // pop domUpdate
            return true; //newSeleniumPage(this, null);
        } else {
            long initTime = System.currentTimeMillis();
            while (System.currentTimeMillis() - initTime < PAGE_LOAD_MAX_WAIT) {
                try {
                    waitForPageToLoad("10");
                    //                    actionStack.pop(); // pop domUpdate
                    return true; //newSeleniumPage(this, null);
                } catch (SeleniumException e) {
                    // We do not want to fail if there was no page reload.
                }
            }
            return false; //this;
        }
    }

    public Page clickAndWaitForLoadIfNecessary(String locator, boolean forceWaitForLoad) {
        String previousHtmlSource = this.getHtmlSource();
        String previousLocation = this.getLocation();
        boolean[] previousVisibilityArray = getVisibilityArray();
        this.click(locator);
        boolean isNewPageLoaded = this.waitForLoadIfNecessary(forceWaitForLoad);
        //        this.getActionStack().lastElement().getType() == Page.Action.ActionType.CLICK_NEW_PAGE || this.getActionStack().lastElement().getType() == Page.Action.ActionType.CLICK_SAME_PAGE;
        Page.Action action;
        if (isNewPageLoaded) {
            String currentLocation = this.getLocation();
            action = currentLocation.equals(previousLocation) ? Page.Action.navigationSamePage(locator)
                    : Page.Action.navigationNewPage(locator, currentLocation);
        } else {
            String currentHtmlSource = this.getHtmlSource();
            if (!currentHtmlSource.equals(previousHtmlSource)) {
                // Compare the number of tags
                if (StringUtils.countOccurrencesOf(currentHtmlSource, "<") == StringUtils
                        .countOccurrencesOf(previousHtmlSource, "<")) {
                    List<String> xpathList = new ArrayList<String>();
                    for (int xpathIndex : compareVisibilityArray(previousVisibilityArray,
                            this.getVisibilityArray())) {
                        xpathList.add("(//*)[" + (xpathIndex + 1) + "]"); //array 0-based, xpath 1-based
                    }
                    //                    if (!xpathList.isEmpty())
                    //                        log.info("Test newly visible content"); // '" + getFailSafeText(xpathList.get(0)) + "'");
                    action = Page.Action.domUpdate(locator,
                            xpathList.size() > 0 ? xpathList.toArray(new String[xpathList.size()]) : null);
                } else {
                    String ajaxContentId = compareHtmlSourceAfterAjaxLoad(previousHtmlSource, currentHtmlSource);
                    //                    log.info("Test new ajax content under id " + ajaxContentId);
                    action = Page.Action.ajaxUpdate(locator, "//*[@id='" + ajaxContentId + "']");
                }
            } else {
                action = Page.Action.noChange(locator);
            }
        }
        this.getActionStack().push(action);
        return this;
    }

    private boolean[] getVisibilityArray() {
        boolean[] visibilityArray = new boolean[this.getXpathCount("//*").intValue()];
        for (int i = 0; i < visibilityArray.length; i++) {
            // array is 0-zero, xpath is 1-based
            visibilityArray[i] = this.isVisible("xpath=(//*)[" + (i + 1) + "]");
        }
        return visibilityArray;
    }

    public static List<Integer> compareVisibilityArray(boolean[] arr1, boolean[] arr2) {
        //        assertEquals(arr1.length, arr2.length);
        List<Integer> results = new ArrayList<Integer>();
        for (int i = 0; i < arr1.length; i++) {
            if (!arr1[i] && arr2[i]) {
                results.add(i);
                break; // Return only the first mismatch for now
            }
        }
        return results;
    }

    /**
     * Compares before and after ajax call.
     * @param previousHtmlSource html before ajax
     * @param currentHtmlSource html after ajax (supposedly containing extra html code)
     * @return the id of the parent which had ajax content appended to.
     */
    private static String compareHtmlSourceAfterAjaxLoad(String previousHtmlSource, String currentHtmlSource) {
        String[] previousSplit = previousHtmlSource.split("(?<=>)");
        String[] currentSplit = currentHtmlSource.split("(?<=>)");
        int i = 0;
        while (previousSplit.length > i && (currentSplit[i].equals(previousSplit[i])
                || (i == 0 || extractIdFromTag(currentSplit[i - 1]) == null))) {
            // continue incrementing if no mismatch in html code OR previous tag does not have an id attribute.
            i++;
        }
        return extractIdFromTag(currentSplit[i - 1]);
    }

    public static final Pattern ID_ATTR_EXTRACTION_PATTERN = Pattern.compile("\\sid=\"(.*?)\"");

    private static String extractIdFromTag(String htmlTag) {
        Matcher m = ID_ATTR_EXTRACTION_PATTERN.matcher(htmlTag);
        String id = null;
        while (m.find()) {
            id = m.group(1);
        }
        return id;
    }

    @Override
    public Page clickLinkAndWait(String linkText) {
        String xpath = "//a[text()='" + linkText + "']";
        return clickAndWait(xpath);
    }

    private void assertUniqueElement(String xpath) {
        int xpathCount = getXpathCount(xpath).intValue();
        if (xpathCount != 1)
            throw new IllegalArgumentException(
                    xpathCount > 1 ? xpath + " locator does not match an unique element. Found " + xpathCount
                            : xpath + " not found on " + this);
    }

    /* Delegating to selenium */

    @Override
    public void setExtensionJs(String extensionJs) {
        selenium.setExtensionJs(extensionJs);
    }

    //    @Override
    //    public void start() {
    //        selenium.start();
    //    }

    //    @Override
    //    public void start(String optionsString) {
    //        selenium.start();
    //    }
    //
    //    @Override
    //    public void start(Object optionsObject) {
    //        selenium.start();
    //    }
    //
    //    @Override
    //    public void stop() {
    //        selenium.stop();
    //    }

    @Override
    public void showContextualBanner() {
        selenium.showContextualBanner();
    }

    @Override
    public void showContextualBanner(String className, String methodName) {
        selenium.showContextualBanner(className, methodName);
    }

    @Override
    public void doubleClick(String locator) {
        selenium.doubleClick(locator);
    }

    @Override
    public void contextMenu(String locator) {
        selenium.contextMenu(locator);
    }

    @Override
    public void clickAt(String locator, String coordString) {
        selenium.clickAt(locator, coordString);
    }

    @Override
    public void doubleClickAt(String locator, String coordString) {
        selenium.doubleClickAt(locator, coordString);
    }

    @Override
    public void contextMenuAt(String locator, String coordString) {
        selenium.contextMenuAt(locator, coordString);
    }

    @Override
    public void fireEvent(String locator, String eventName) {
        selenium.fireEvent(locator, eventName);
    }

    @Override
    public void focus(String locator) {
        selenium.focus(locator);
    }

    @Override
    public void keyPress(String locator, String keySequence) {
        selenium.keyPress(locator, keySequence);
    }

    @Override
    public void shiftKeyDown() {
        selenium.shiftKeyDown();
    }

    @Override
    public void shiftKeyUp() {
        selenium.shiftKeyUp();
    }

    @Override
    public void metaKeyDown() {
        selenium.metaKeyDown();
    }

    @Override
    public void metaKeyUp() {
        selenium.metaKeyUp();
    }

    @Override
    public void altKeyDown() {
        selenium.altKeyDown();
    }

    @Override
    public void altKeyUp() {
        selenium.altKeyUp();
    }

    @Override
    public void controlKeyDown() {
        selenium.controlKeyDown();
    }

    @Override
    public void controlKeyUp() {
        selenium.controlKeyUp();
    }

    @Override
    public void keyDown(String locator, String keySequence) {
        selenium.keyDown(locator, keySequence);
    }

    @Override
    public void keyUp(String locator, String keySequence) {
        selenium.keyUp(locator, keySequence);
    }

    @Override
    public void mouseOver(String locator) {
        selenium.mouseOver(locator);
    }

    @Override
    public void mouseOut(String locator) {
        selenium.mouseOut(locator);
    }

    @Override
    public void mouseDown(String locator) {
        selenium.mouseDown(locator);
    }

    @Override
    public void mouseDownRight(String locator) {
        selenium.mouseDownRight(locator);
    }

    @Override
    public void mouseDownAt(String locator, String coordString) {
        selenium.mouseDownAt(locator, coordString);
    }

    @Override
    public void mouseDownRightAt(String locator, String coordString) {
        selenium.mouseDownRightAt(locator, coordString);
    }

    @Override
    public void mouseUp(String locator) {
        selenium.mouseUp(locator);
    }

    @Override
    public void mouseUpRight(String locator) {
        selenium.mouseUpRight(locator);
    }

    @Override
    public void mouseUpAt(String locator, String coordString) {
        selenium.mouseUpAt(locator, coordString);
    }

    @Override
    public void mouseUpRightAt(String locator, String coordString) {
        selenium.mouseUpRightAt(locator, coordString);
    }

    @Override
    public void mouseMove(String locator) {
        selenium.mouseMove(locator);
    }

    @Override
    public void mouseMoveAt(String locator, String coordString) {
        selenium.mouseMoveAt(locator, coordString);
    }

    @Override
    public Page input(String value) {
        return input(++inputCounter, value);
    }

    @Override
    public Page input(int inputIndex, String value) {
        return type("//input[" + inputIndex + "]", value);
    }

    @Override
    public Page type(String locator, String value) {
        selenium.type(locator, value);
        return this;
    }

    @Override
    public void typeKeys(String locator, String value) {
        selenium.typeKeys(locator, value);
    }

    @Override
    public void setSpeed(String value) {
        selenium.setSpeed(value);
    }

    @Override
    public String getSpeed() {
        return selenium.getSpeed();
    }

    @Override
    public String getLog() {
        return selenium.getLog();
    }

    @Override
    public Page check(String locator) {
        selenium.check(locator);
        return this;
    }

    @Override
    public Page uncheck(String locator) {
        selenium.uncheck(locator);
        return this;
    }

    @Override
    public Page select(String selectLocator, String optionLabel) {
        assertUniqueElement(selectLocator);
        selenium.select(selectLocator, "label=" + optionLabel);
        return this;
    }

    @Override
    public Page select(String selectLocator, int index) {
        assertUniqueElement(selectLocator);
        selenium.select(selectLocator, "index=" + index);
        return this;
    }

    private Page select(int selectIndex, int index) {
        selenium.select("//select[" + selectIndex + "]", "index=" + index);
        return this;
    }

    @Override
    public Page select(int index) {
        selenium.select("//select[" + ++selectCounter + "]", "index=" + index);
        return this;
    }

    @Override
    public Page selectAny() {
        int selectIndex = ++selectCounter;
        int optionIndex = randomInt(1,
                getXpathCount("//select[" + selectIndex + "]/option[@value!='']").intValue());
        return select(selectIndex, optionIndex);
    }

    protected static int randomInt(int minInclusive, int maxExclusive) {
        return new Random(System.currentTimeMillis()).nextInt(maxExclusive) + minInclusive;
    }

    @Override
    public Page addSelection(String locator, String optionLocator) {
        selenium.addSelection(locator, optionLocator);
        return this;
    }

    @Override
    public Page removeSelection(String locator, String optionLocator) {
        selenium.removeSelection(locator, optionLocator);
        return this;
    }

    @Override
    public Page removeAllSelections(String locator) {
        selenium.removeAllSelections(locator);
        return this;
    }

    @Override
    public Page submitForm() {
        //        return submit("//form");
        return clickAndWait("//form//input[@type='submit']");
    }

    @Override
    public Page submit(String formLocator) {
        assertUniqueElement(formLocator);
        selenium.submit(formLocator);
        return this;
    }

    //    @Override
    //    public void open(String url, String ignoreResponseCode) {
    //        selenium.open(url, ignoreResponseCode);
    //    }

    //    @Override
    //    public void open(String url) {
    //        selenium.open();
    //    }

    //    @Override
    //    public void openWindow(String url, String windowID) {
    //        selenium.openWindow();
    //    }

    @Override
    public void selectWindow(String windowID) {
        selenium.selectWindow(windowID);
    }

    @Override
    public void selectPopUp(String windowID) {
        selenium.selectPopUp(windowID);
    }

    @Override
    public void deselectPopUp() {
        selenium.deselectPopUp();
    }

    @Override
    public void selectFrame(String locator) {
        selenium.selectFrame(locator);
    }

    @Override
    public boolean getWhetherThisFrameMatchFrameExpression(String currentFrameString, String target) {
        return selenium.getWhetherThisFrameMatchFrameExpression(currentFrameString, target);
    }

    @Override
    public boolean getWhetherThisWindowMatchWindowExpression(String currentWindowString, String target) {
        return selenium.getWhetherThisWindowMatchWindowExpression(currentWindowString, target);
    }

    @Override
    public void waitForPopUp(String windowID, String timeout) {
        selenium.waitForPopUp(windowID, timeout);
    }

    @Override
    public void chooseCancelOnNextConfirmation() {
        selenium.chooseCancelOnNextConfirmation();
    }

    @Override
    public void chooseOkOnNextConfirmation() {
        selenium.chooseOkOnNextConfirmation();
    }

    @Override
    public void answerOnNextPrompt(String answer) {
        selenium.answerOnNextPrompt(answer);
    }

    @Override
    public void goBack() {
        selenium.goBack();
    }

    @Override
    public void refresh() {
        selenium.refresh();
    }

    @Override
    public void close() {
        selenium.close();
    }

    @Override
    public boolean isAlertPresent() {
        return selenium.isAlertPresent();
    }

    @Override
    public boolean isPromptPresent() {
        return selenium.isPromptPresent();
    }

    @Override
    public boolean isConfirmationPresent() {
        return selenium.isConfirmationPresent();
    }

    @Override
    public String getAlert() {
        return selenium.getAlert();
    }

    @Override
    public String getConfirmation() {
        return selenium.getConfirmation();
    }

    @Override
    public String getPrompt() {
        return selenium.getPrompt();
    }

    @Override
    public String getLocation() {
        return selenium.getLocation();
    }

    @Override
    public String getTitle() {
        return selenium.getTitle();
    }

    @Override
    public String getBodyText() {
        return selenium.getBodyText();
    }

    @Override
    public String getValue(String locator) {
        return selenium.getValue(locator);
    }

    @Override
    public String getText(String locator) {
        return selenium.getText(locator);
    }

    @Override
    public void highlight(String locator) {
        selenium.highlight(locator);
    }

    @Override
    public String getEval(String script) {
        return selenium.getEval(script);
    }

    @Override
    public boolean isChecked(String locator) {
        return selenium.isChecked(locator);
    }

    @Override
    public String getTable(String tableCellAddress) {
        return selenium.getTable(tableCellAddress);
    }

    @Override
    public String[] getSelectedLabels(String selectLocator) {
        return selenium.getSelectedLabels(selectLocator);
    }

    @Override
    public String getSelectedLabel(String selectLocator) {
        return selenium.getSelectedLabel(selectLocator);
    }

    @Override
    public String[] getSelectedValues(String selectLocator) {
        return selenium.getSelectedValues(selectLocator);
    }

    @Override
    public String getSelectedValue(String selectLocator) {
        return selenium.getSelectedValue(selectLocator);
    }

    @Override
    public String[] getSelectedIndexes(String selectLocator) {
        return selenium.getSelectedIndexes(selectLocator);
    }

    @Override
    public String getSelectedIndex(String selectLocator) {
        return selenium.getSelectedIndex(selectLocator);
    }

    @Override
    public String[] getSelectedIds(String selectLocator) {
        return selenium.getSelectedIds(selectLocator);
    }

    @Override
    public String getSelectedId(String selectLocator) {
        return selenium.getSelectedId(selectLocator);
    }

    @Override
    public boolean isSomethingSelected(String selectLocator) {
        return selenium.isSomethingSelected(selectLocator);
    }

    @Override
    public String[] getSelectOptions(String selectLocator) {
        return selenium.getSelectOptions(selectLocator);
    }

    @Override
    public String getAttribute(String attributeLocator) {
        return selenium.getAttribute(attributeLocator);
    }

    @Override
    public boolean isTextPresent(String pattern) {
        return selenium.isTextPresent(pattern);
    }

    @Override
    public boolean isElementPresent(String locator) {
        return selenium.isElementPresent(locator);
    }

    @Override
    public boolean isVisible(String locator) {
        return selenium.isVisible(locator);
    }

    @Override
    public boolean isEditable(String locator) {
        return selenium.isEditable(locator);
    }

    @Override
    public String[] getAllButtons() {
        return selenium.getAllButtons();
    }

    @Override
    public String[] getAllLinks() {
        return selenium.getAllLinks();
    }

    @Override
    public String[] getAllFields() {
        return selenium.getAllFields();
    }

    @Override
    public String[] getAttributeFromAllWindows(String attributeName) {
        return selenium.getAttributeFromAllWindows(attributeName);
    }

    @Override
    public void dragdrop(String locator, String movementsString) {
        selenium.dragdrop(locator, movementsString);
    }

    @Override
    public void setMouseSpeed(String pixels) {
        selenium.setMouseSpeed(pixels);
    }

    @Override
    public Number getMouseSpeed() {
        return selenium.getMouseSpeed();
    }

    @Override
    public void dragAndDrop(String locator, String movementsString) {
        selenium.dragAndDrop(locator, movementsString);
    }

    @Override
    public void dragAndDropToObject(String locatorOfObjectToBeDragged, String locatorOfDragDestinationObject) {
        selenium.dragAndDropToObject(locatorOfObjectToBeDragged, locatorOfDragDestinationObject);
    }

    @Override
    public void windowFocus() {
        selenium.windowFocus();
    }

    @Override
    public void windowMaximize() {
        selenium.windowMaximize();
    }

    @Override
    public String[] getAllWindowIds() {
        return selenium.getAllWindowIds();
    }

    @Override
    public String[] getAllWindowNames() {
        return selenium.getAllWindowNames();
    }

    @Override
    public String[] getAllWindowTitles() {
        return selenium.getAllWindowTitles();
    }

    @Override
    public String getHtmlSource() {
        return selenium.getHtmlSource();
    }

    @Override
    public void setCursorPosition(String locator, String position) {
        selenium.setCursorPosition(locator, position);
    }

    @Override
    public Number getElementIndex(String locator) {
        return selenium.getElementIndex(locator);
    }

    @Override
    public boolean isOrdered(String locator1, String locator2) {
        return selenium.isOrdered(locator1, locator2);
    }

    @Override
    public Number getElementPositionLeft(String locator) {
        return selenium.getElementPositionLeft(locator);
    }

    @Override
    public Number getElementPositionTop(String locator) {
        return selenium.getElementPositionTop(locator);
    }

    @Override
    public Number getElementWidth(String locator) {
        return selenium.getElementWidth(locator);
    }

    @Override
    public Number getElementHeight(String locator) {
        return selenium.getElementHeight(locator);
    }

    @Override
    public Number getCursorPosition(String locator) {
        return selenium.getCursorPosition(locator);
    }

    @Override
    public String getExpression(String expression) {
        return selenium.getExpression(expression);
    }

    @Override
    public Number getXpathCount(String xpath) {
        assertIsCurrentPage();
        return selenium.getXpathCount(xpath.replaceFirst("xpath=", "")); // getXPathCount does not accept 'xpath=' prefix
    }

    @Override
    public Number getCssCount(String css) {
        return selenium.getCssCount(css);
    }

    @Override
    public void assignId(String locator, String identifier) {
        selenium.assignId(locator, identifier);
    }

    @Override
    public void allowNativeXpath(String allow) {
        selenium.allowNativeXpath(allow);
    }

    @Override
    public void ignoreAttributesWithoutValue(String ignore) {
        selenium.ignoreAttributesWithoutValue(ignore);
    }

    @Override
    public void waitForCondition(String script, String timeout) {
        selenium.waitForCondition(script, timeout);
    }

    @Override
    public void setTimeout(String timeout) {
        selenium.setTimeout(timeout);
    }

    @Override
    public void waitForPageToLoad(String timeout) {
        selenium.waitForPageToLoad(timeout);
    }

    @Override
    public void waitForFrameToLoad(String frameAddress, String timeout) {
        selenium.waitForFrameToLoad(frameAddress, timeout);
    }

    @Override
    public String getCookie() {
        return selenium.getCookie();
    }

    @Override
    public String getCookieByName(String name) {
        return selenium.getCookieByName(name);
    }

    @Override
    public boolean isCookiePresent(String name) {
        return selenium.isCookiePresent(name);
    }

    @Override
    public void createCookie(String nameValuePair, String optionsString) {
        selenium.createCookie(nameValuePair, optionsString);
    }

    @Override
    public void deleteCookie(String name, String optionsString) {
        selenium.deleteCookie(name, optionsString);
    }

    @Override
    public void deleteAllVisibleCookies() {
        selenium.deleteAllVisibleCookies();
    }

    @Override
    public void setBrowserLogLevel(String logLevel) {
        selenium.setBrowserLogLevel(logLevel);
    }

    @Override
    public void runScript(String script) {
        selenium.runScript(script);
    }

    @Override
    public void addLocationStrategy(String strategyName, String functionDefinition) {
        selenium.addLocationStrategy(strategyName, functionDefinition);
    }

    @Override
    public void captureEntirePageScreenshot(String filename, String kwargs) {
        selenium.captureEntirePageScreenshot(filename, kwargs);
    }

    @Override
    public void rollup(String rollupName, String kwargs) {
        selenium.rollup(rollupName, kwargs);
    }

    @Override
    public void addScript(String scriptContent, String scriptTagId) {
        selenium.addScript(scriptContent, scriptTagId);
    }

    @Override
    public void removeScript(String scriptTagId) {
        selenium.removeScript(scriptTagId);
    }

    @Override
    public void useXpathLibrary(String libraryName) {
        selenium.useXpathLibrary(libraryName);
    }

    @Override
    public void setContext(String context) {
        selenium.setContext(context);
    }

    @Override
    public void attachFile(String fieldLocator, String fileLocator) {
        selenium.attachFile(fieldLocator, fileLocator);
    }

    @Override
    public void captureScreenshot(String filename) {
        selenium.captureScreenshot(filename);
    }

    @Override
    public String captureScreenshotToString() {
        return selenium.captureScreenshotToString();
    }

    @Override
    public String captureNetworkTraffic(String type) {
        return selenium.captureNetworkTraffic(type);
    }

    @Override
    public void addCustomRequestHeader(String key, String value) {
        selenium.addCustomRequestHeader(key, value);
    }

    @Override
    public String captureEntirePageScreenshotToString(String kwargs) {
        return selenium.captureEntirePageScreenshotToString(kwargs);
    }

    @Override
    public void shutDownSeleniumServer() {
        selenium.shutDownSeleniumServer();
    }

    @Override
    public String retrieveLastRemoteControlLogs() {
        return selenium.retrieveLastRemoteControlLogs();
    }

    @Override
    public void keyDownNative(String keycode) {
        selenium.keyDownNative(keycode);
    }

    @Override
    public void keyUpNative(String keycode) {
        selenium.keyUpNative(keycode);
    }

    @Override
    public void keyPressNative(String keycode) {
        selenium.keyPressNative(keycode);
    }

    @Override
    public String toString() {
        Stack<URL> locationStack = getLocationStack();
        return locationStack.get(locationStack.size() - 1).toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        SeleniumPage that = (SeleniumPage) o;
        Stack<URL> locationStack = getLocationStack();
        return locationStack.lastElement().equals(that.getLocationStack().lastElement());
    }

    @Override
    public int hashCode() {
        Stack<URL> locationStack = getLocationStack();
        return locationStack.lastElement().hashCode();
    }

    /* End of generated delegation code */

    public static URL toLocationPath(String location) {
        try {
            URL fullUrl = new URL(location);
            // We just throw the query string if any
            return new URL(fullUrl.getProtocol(), fullUrl.getHost(), fullUrl.getPort(), fullUrl.getPath());
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
    }
}