package org.seleniumhq.selenium.fluent;

import org.junit.Test;
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;

import java.util.List;

import static com.thoughtworks.selenium.SeleneseTestBase.assertEquals;
import static junit.framework.TestCase.fail;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;

public class StaleRecoveringTest {

    @Test(timeout = 60000)
    public void vanillaWebDriverShouldCatchStaleExceptionAndBeAbleToCarryOnAnyway() {

        // We have to simulate a stale element exception as
        // we can't find a real-world example
        FirstGetAttributeIsStaleDriver driver = new FirstGetAttributeIsStaleDriver();

        driver.get("http://seleniumhq.github.io/fluent-selenium/7753/index.html");
        WebElement elem;
        try {
            elem = driver.findElement(By.id("cheddarCheeseLoginPassword"));
            elem.sendKeys("bar");
            getAndVerify(elem);
            fail("should have barfed");
        } catch(StaleElementReferenceException sere) {
            elem = driver.findElement(By.id("cheddarCheeseLoginPassword"));
            getAndVerify(elem);
        } finally {
            driver.quit();
        }

        assertEquals(2, driver.countOfGetAttribute[0]);

    }

    private void getAndVerify(WebElement elem) {
        String val = elem.getAttribute("value");
        assertEquals("bar", val);
    }

    @Test
    public void knownStaleCaseCanBeOvercomeInFluentWebDriverToo() {

        // We have to simulate a stale element exception as
        // we can't find a real-world example
        FirstGetAttributeIsStaleDriver driver = new FirstGetAttributeIsStaleDriver();

        driver.get("http://seleniumhq.github.io/fluent-selenium/7753/index.html");

        FluentWebDriver fwd = new FluentWebDriver(driver);

        try {
            String val = fwd.input(By.id("cheddarCheeseLoginPassword"))
                    .sendKeys(Keys.chord(Keys.CONTROL, "a") + "bar")
                    .getAttribute("value").toString();
            try {
                assertThat(val, equalTo("bar"));
            } catch (AssertionError e) {
                // unrelated to the staleness, sometimes the field isn't getting overwritten in the sendKeys()
                assertThat(val, equalTo("barI can Haz Password"));
            }
        } finally {
            driver.quit();
        }

        assertEquals(2, driver.countOfGetAttribute[0]);

    }

    private static class FirstGetAttributeIsStaleDriver extends FirefoxDriver {
        public final int[] countOfGetAttribute = {0};

        @Override
        public WebElement findElementById(String using) {
            final WebElement we = super.findElementById(using);
            return new WebElement() {
                public void click() {
                    we.click();
                }

                public void submit() {
                    we.submit();
                }

                public void sendKeys(CharSequence... keysToSend) {
                    we.sendKeys(keysToSend);
                }

                public void clear() {
                    we.clear();
                }

                public String getTagName() {
                    return we.getTagName();
                }

                public String getAttribute(String name) {
                    if (countOfGetAttribute[0] == 0) {
                        countOfGetAttribute[0]++;
                        throw new StaleElementReferenceException("boop");
                    }
                    countOfGetAttribute[0]++;
                    return we.getAttribute(name);
                }

                public boolean isSelected() {
                    return we.isSelected();
                }

                public boolean isEnabled() {
                    return we.isEnabled();
                }

                public String getText() {
                    return we.getText();
                }

                public List<WebElement> findElements(By by) {
                    return we.findElements(by);
                }

                public WebElement findElement(By by) {
                    return we.findElement(by);
                }

                public boolean isDisplayed() {
                    return we.isDisplayed();
                }

                public Point getLocation() {
                    return we.getLocation();
                }

                public Dimension getSize() {
                    return we.getSize();
                }

                public String getCssValue(String propertyName) {
                    return we.getCssValue(propertyName);
                }

                public <X> X getScreenshotAs(OutputType<X> outputType) throws WebDriverException { return we.getScreenshotAs(outputType); }
            };
        }
    }
}

@@ -1806,16 +1806,75 @@
 .html%22);
+%0A        assertEquals(false, driver.staleElementThrown%5B0%5D);
 %0A%0A      
@@ -2542,32 +2542,90 @@
 etAttribute%5B0%5D);
+%0A        assertEquals(true, driver.staleElementThrown%5B0%5D);
 %0A%0A    %7D%0A%0A    pri
@@ -2750,16 +2750,77 @@
 e = %7B0%7D;
+%0A        public final boolean%5B%5D staleElementThrown = %7Bfalse%7D;
 %0A%0A      
@@ -3654,32 +3654,86 @@
 Attribute%5B0%5D++;%0A
+                        staleElementThrown%5B0%5D = true;%0A
                 
@@ -3803,33 +3803,44 @@
                %7D
-%0A
+ else %7B%0A    
                 
@@ -3881,32 +3881,36 @@
                 
+    
 return we.getAtt
@@ -3919,24 +3919,46 @@
 bute(name);%0A
+                    %7D%0A
             

make test clearer