package nl.hsac.fitnesse.fixture.web;

import nl.hsac.fitnesse.fixture.util.SeleniumHelper;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BrowserTest extends SlimFixture {
    private static final Pattern PATTERN = Pattern.compile("<a href=\"(.*?)\">(.*?)</a>", Pattern.CASE_INSENSITIVE);

    private SeleniumHelper seleniumHelper = getEnvironment().getSeleniumHelper();

    protected SeleniumHelper getSeleniumHelper() {
        return seleniumHelper;
    }

    public boolean open(String htmlLink) {
        String url = urlFromLink(htmlLink);
        seleniumHelper.navigate().to(url);
        return true;
    }

    public String pageTitle() {
        return seleniumHelper.getPageTitle();
    }

    public boolean enterAs(String value, String place) {
        return enterFor(value, place);
    }

    public boolean enterFor(String value, String place) {
        boolean result = false;
        WebElement element = getElement(place);
        if (element != null) {
            element.sendKeys(value);
            result = true;
        }
        return result;
    }

    public boolean selectAs(String value, String place) {
        return selectFor(value, place);
    }

    public boolean selectFor(String value, String place) {
        // choose option for select, if possible
        boolean result = clickSelectOption(place, value);
        if (!result) {
            // try to click the first element with right value
            result = click(value);
        }
        return result;
    }

    public boolean enterForHidden(String value, String idOrName) {
        return seleniumHelper.setHiddenInputValue(idOrName, value);
    }

    private boolean clickSelectOption(String selectPlace, String optionValue) {
        boolean result = false;
        WebElement element = getElement(selectPlace);
        if (element != null) {
            if (isSelect(element)) {
                String id = element.getAttribute("id");
                result = clickOption(id, "//select[@id='%s']//option[text()='%s']", optionValue);
                if (!result) {
                    result = clickOption(id, "//select[@id='%s']//option[contains(text(), '%s')]", optionValue);
                }
            }
        }
        return result;
    }

    private boolean clickOption(String selectId, String optionXPath, String optionValue) {
        boolean result = false;
        By optionWithText = seleniumHelper.byXpath(optionXPath, selectId, optionValue);
        WebElement option = seleniumHelper.findElement(true, optionWithText);
        if (option != null) {
            option.click();
            result = true;
        }
        return result;
    }

    public boolean click(String place) {
        boolean result = false;
        WebElement element = getElement(place);
        if (element != null) {
            element.click();
            result = true;
        }
        return result;
    }

    public String valueOf(String place) {
        return valueFor(place);
    }

    public String valueFor(String place) {
        String result = null;
        WebElement element = getElement(place);
        if (element != null) {
            if (isSelect(element)) {
                String id = element.getAttribute("id");
                By selectedOption = seleniumHelper.byXpath("//select[@id='%s']//option[@selected]", id);
                WebElement option = seleniumHelper.findElement(true, selectedOption);
                if (option != null) {
                    result = option.getText();
                }
            } else {
                result = element.getAttribute("value");
            }
        }
        return result;
    }

    private boolean isSelect(WebElement element) {
        return "select".equalsIgnoreCase(element.getTagName());
    }

    public boolean clear(String place) {
        boolean result = false;
        WebElement element = getElement(place);
        if (element != null) {
            element.clear();
            result = true;
        }
        return result;
    }

    protected WebElement getElement(String place) {
        return seleniumHelper.getElement(place);
    }

    private String urlFromLink(String htmlLink) {
        String result = null;
        Matcher matcher = PATTERN.matcher(htmlLink);
        if (matcher.matches()) {
            result = matcher.group(1);
        }
        return result;
    }
}

@@ -219,16 +219,126 @@
 Pattern;
+%0Aimport org.openqa.selenium.support.ui.ExpectedCondition;%0Aimport org.openqa.selenium.support.ui.WebDriverWait;
 %0A%0Apublic
@@ -374,24 +374,68 @@
 imFixture %7B%0A
+    static final int MAX_WAIT_SECONDS = 30;%0A
     private 
@@ -1219,32 +1219,79 @@
 ment != null) %7B%0A
+            String keys = cleanupValue(value);%0A
             elem
@@ -1303,21 +1303,20 @@
 endKeys(
-value
+keys
 );%0A     
@@ -4438,32 +4438,823 @@
 (place);%0A    %7D%0A%0A
+    protected Boolean waitFor(ExpectedCondition%3CBoolean%3E condition) %7B%0A        return waitDriver().until(condition).booleanValue();%0A    %7D%0A%0A    private WebDriverWait waitDriver() %7B%0A        return new WebDriverWait(getSeleniumHelper().driver(), MAX_WAIT_SECONDS);%0A    %7D%0A%0A    /**%0A     * Removes result of wiki formatting (for e.g. email addresses) if needed.%0A     * @param rawValue value as received from Fitnesse.%0A     * @return rawValue if it was just text, cleaned version if it was not.%0A     */%0A    protected String cleanupValue(String rawValue) %7B%0A        String result = null;%0A        Matcher matcher = PATTERN.matcher(rawValue);%0A        if (matcher.matches()) %7B%0A            result = matcher.group(2);%0A        %7D else %7B%0A            result = rawValue;%0A        %7D%0A        return result;%0A    %7D%0A%0A
     private Stri

Bring changes to BrowserTest from LNG to this branch