dimasmith
2/28/2013 - 12:48 AM

Made intentional error during coding. clickCloseIssueButton() (at the very end of file) method was calling itself but since it uses WebDrive

Made intentional error during coding. clickCloseIssueButton() (at the very end of file) method was calling itself but since it uses WebDriver calls that nesting lead to StaleElementReferenceException far earlier than to StackOverflowException. Spent 15 mins to figure it out.

package selenium.camp;

import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.CoreMatchers.containsString;
import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import static org.openqa.selenium.support.ui.ExpectedConditions.presenceOfElementLocated;
import static org.openqa.selenium.support.ui.ExpectedConditions.refreshed;
import org.openqa.selenium.support.ui.WebDriverWait;

public class GitHubIssuesTest {

    private static final String BASE_URL = "https://github.com";
    private WebDriver driver;

    @Before
    public void setUp() {
        driver = new FirefoxDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get(BASE_URL);
        loginAs("user", "password");
        switchToRepository("test-repo");
    }
    
    @Test
    public void closeSingleIssue() {
        openIssuesList();
        String issueId = createIssue("Issue that will be closed");
        openIssuesList();
        closeIssue(issueId);
        assertTrue("Issue list element is still present", isIssueListedItemRemoved(issueId));
    }

    @After
    public void tearDown() {
        driver.quit();
    }

    private void loginAs(String login, String password) {
        driver.findElement(By.linkText("Sign in")).click();

        driver.findElement(By.id("login_field")).sendKeys(login);
        driver.findElement(By.id("password")).sendKeys(password);
        driver.findElement(By.name("commit")).click();
    }

    private void switchToRepository(String repositoryName) {
        driver.findElement(By.partialLinkText(repositoryName)).click();
    }

    private void openIssuesList() {
        driver.findElement(By.partialLinkText("Issues")).click();
    }

    /**
     * Creates issue with summary as provided and returns issue identifier.
     *
     * @param summary
     * @return
     */
    private String createIssue(String summary) {
        driver.findElement(By.linkText("New Issue")).click();
        driver.findElement(By.id("issue_title")).sendKeys(summary);
        driver.findElement(By.cssSelector("button.button.primary")).click();
        String issueId = driver.findElement(By.cssSelector(".issue-head .number strong")).getText();
        issueId = issueId.substring(1);
        return issueId;

    }

    private WebElement getIssueListElement(String issueId) {
        String issueLocator = "issue_" + issueId;
        return driver.findElement(By.id(issueLocator));
    }

    private void closeAllIssues() {
        List<WebElement> issueCheckboxes = driver.findElements(By.cssSelector(".issues td.select-toggle input[type='checkbox']"));
        for (WebElement issueCheckbox : issueCheckboxes) {
            issueCheckbox.click();
        }

        clickCloseIssueButton();
    }

    private String getIssuesMessageText() {
        String message = driver.findElement(By.cssSelector(".issues .none p")).getText();
        message = message.trim();
        return message;
    }

    private boolean isIssueListed(String issueId) {                
        final String locator = String.format("issue_%s", issueId);        
        return !driver.findElements(By.id(locator)).isEmpty();
    }
    
    private boolean isIssueListedItemRemoved(String issueId) {                
        final String locator = String.format("issue_%s", issueId);        
        WebDriverWait wait = new WebDriverWait(driver, 10);
        return wait.until(ExpectedConditions.stalenessOf(driver.findElement(By.id(locator))));        
    }

    private void closeIssue(String issueId) {
        WebElement issueCheckBox = getIssueListElement(issueId).findElement(By.cssSelector("input[type='checkbox']"));
        issueCheckBox.click();
        clickCloseIssueButton();        
    }

    private void clickCloseIssueButton() {
        driver.findElement(By.partialLinkText("Close")).click();
        clickCloseIssueButton();       
    }
}