Permalink
Browse files

Improved AJAX search. Added error message when no beers found for the

given criteria.
  • Loading branch information...
1 parent 0ac5e8a commit 809682e00d0a794c78e9995123c7a0bf53f067b8 @bartoszmajsak committed Mar 24, 2012
@@ -1,18 +1,19 @@
package org.arquillian.example.repository;
-import org.arquillian.example.repository.exception.UnknownBeerCriteriaException;
+import java.util.EnumSet;
+import java.util.Set;
import com.google.common.base.Preconditions;
-
public enum BeerCriteria
{
ALL("all"),
CHEAPEST("cheapest"),
STRONGEST("strongest"),
BELGIUM("from belgium"),
SWITZERLAND("from switzerland"),
- NONE("none");
+ NONE("none"),
+ UNKNOWN("---");
private final String criteriaString;
@@ -27,14 +28,16 @@ public static BeerCriteria fromStringDescription(String criteriaString)
Preconditions.checkArgument(!criteriaString.trim().isEmpty(), "Criteria string should not be empty");
criteriaString = criteriaString.trim().toLowerCase();
- for (BeerCriteria beerCriteria : values())
+
+ final Set<BeerCriteria> handledCriteria = EnumSet.complementOf(EnumSet.of(UNKNOWN));
+ for (BeerCriteria beerCriteria : handledCriteria)
{
if (criteriaString.equals(beerCriteria.criteriaString))
{
return beerCriteria;
}
}
- throw new UnknownBeerCriteriaException("Cannot resolve criteria for given string representation: '" + criteriaString + "'");
+ return UNKNOWN;
}
}
@@ -1,27 +0,0 @@
-package org.arquillian.example.repository.exception;
-
-public class UnknownBeerCriteriaException extends RuntimeException
-{
-
- private static final long serialVersionUID = 4192615774516733111L;
-
- public UnknownBeerCriteriaException()
- {
- }
-
- public UnknownBeerCriteriaException(String message)
- {
- super(message);
- }
-
- public UnknownBeerCriteriaException(Throwable cause)
- {
- super(cause);
- }
-
- public UnknownBeerCriteriaException(String message, Throwable cause)
- {
- super(message, cause);
- }
-
-}
@@ -35,6 +35,7 @@
case STRONGEST:
return beerRepository.strongest();
case NONE:
+ case UNKNOWN:
return Collections.emptySet();
}
@@ -2,11 +2,8 @@
import static org.fest.assertions.Assertions.assertThat;
-import org.arquillian.example.repository.BeerCriteria;
-import org.arquillian.example.repository.exception.UnknownBeerCriteriaException;
import org.junit.Test;
-
public class BeerCriteriaTest
{
@@ -49,8 +46,8 @@ public void shouldThrowExceptionIfCriteriaStringIsBlank() throws Exception
// exception should be thrown
}
- @Test(expected = UnknownBeerCriteriaException.class)
- public void shouldThrowExceptionIfCriteriaStringIsNotRecognized() throws Exception
+ @Test
+ public void shouldReturnUnknownIfCriteriaStringIsNotRecognized() throws Exception
{
// given
String criteriaString = "everything";
@@ -59,7 +56,7 @@ public void shouldThrowExceptionIfCriteriaStringIsNotRecognized() throws Excepti
BeerCriteria beerCriteria = BeerCriteria.fromStringDescription(criteriaString);
// then
- // exception should be thrown
+ assertThat(beerCriteria).isEqualTo(BeerCriteria.UNKNOWN);
}
@Test
@@ -1,9 +1,11 @@
package org.arquillian.example.controller;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
import javax.enterprise.context.RequestScoped;
+import javax.faces.event.AjaxBehaviorEvent;
import javax.inject.Inject;
import javax.inject.Named;
@@ -17,29 +19,52 @@
public class BeerAdvisorController
{
+ private static final String NONE = "none";
+
+ private boolean notFound;
+
+ private List<Beer> beers = Collections.emptyList();
+
@Inject
- BeerService beerService;
+ private BeerService beerService;
- private String filter;
+ private String criteria;
- public List<Beer> getBeers()
+ public void loadBeers(AjaxBehaviorEvent event)
{
- if (filter == null || filter.trim().isEmpty())
+ if (criteria == null || criteria.trim().isEmpty())
{
- filter = "none";
+ criteria = NONE;
}
- final Set<Beer> result = beerService.fetchByCriteria(filter);
- return Lists.newArrayList(result);
+
+ final Set<Beer> result = beerService.fetchByCriteria(criteria);
+ notFound = result.isEmpty() && !NONE.equals(criteria);
+ beers = Lists.newArrayList(result);
+ }
+
+ public List<Beer> getBeers()
+ {
+ return beers;
+ }
+
+ public String getCriteria()
+ {
+ return criteria;
+ }
+
+ public void setCriteria(String filter)
+ {
+ this.criteria = filter;
}
- public String getFilter()
+ public boolean isNotFound()
{
- return filter;
+ return notFound;
}
- public void setFilter(String filter)
+ public void setNotFound(boolean notFound)
{
- this.filter = filter;
+ this.notFound = notFound;
}
}
@@ -5,14 +5,21 @@
template="template.xhtml">
<ui:define name="content">
- <h:form id="advisor">
+ <h:form id="advisor" onkeypress="return event.keyCode != 13">
<div id="search_beer">
- <h:inputText id="beerSearch" value="#{beerAdvisorController.filter}"
- styleClass="beer-search-field">
- <f:ajax event="keyup" render="beers" />
+ <h:inputText id="beerSearch" value="#{beerAdvisorController.criteria}"
+ styleClass="beer-search-field"
+ onkeypress="if (event.keyCode == 13) { this.blur(); }">
+ <f:ajax event="blur" render="beers"
+ listener="#{beerAdvisorController.loadBeers}" />
</h:inputText>
</div>
<h:panelGroup id="beers">
+ <div class="criteria-not-found">
+ <h:outputText value="No beers matching specified criteria '#{beerAdvisorController.criteria}'."
+ id="error"
+ rendered="#{beerAdvisorController.notFound}" />
+ </div>
<table id="beer-results-table">
<thead>
<th>Name</th>
@@ -228,4 +228,11 @@ div#menu_content div#top_logo a {
#beer-results-table tbody tr:hover td {
color: #009;
+}
+
+.criteria-not-found {
+ margin: 16px 0px 0px 50px;
+ color:#f00;
+ font-size: 16px;
+ font-weight:bold;
}
@@ -89,4 +89,18 @@ class BeerAdvisorSpecification extends Specification
.shouldHaveAlcoholPercentageOf(55.0)
}
+ @Test
+ def "Should display error message when no result found for criteria"()
+ {
+ given: "I'm on the main page"
+ def beerAdvisorPage = new BeerAdvisorPage(driver, deploymentUrl.toString())
+
+ when: "I enter a criteria for which there is no result"
+ def beers = beerAdvisorPage.searchFor("aAa")
+
+ then: "Error message should be displayed"
+ Thread.sleep(1000)
+ beerAdvisorPage.errorMessageShouldBeDisplayed("No beers matching specified criteria 'aAa'")
+ }
+
}
@@ -1,14 +1,21 @@
package org.arquillian.example.ui.web;
+import static org.fest.assertions.Assertions.assertThat;
+
+import java.util.Collections;
import java.util.List;
+import java.util.Set;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
+import org.openqa.selenium.NoSuchElementException;
+import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.ExpectedCondition;
+import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import com.google.common.collect.Lists;
@@ -26,9 +33,9 @@
public class BeerAdvisorPage
{
- private static final int SECONDS_TO_WAIT = 2;
+ private static final int SECONDS_TO_WAIT = 1;
- private static final int POLL_EVERY_MS = 15;
+ private static final int POLL_EVERY_MS = 60;
private static final String RESULT_TABLE_XPATH = "//table[@id='beer-results-table']/tbody/tr";
@@ -48,10 +55,18 @@ public BeerAdvisorPage(WebDriver driver, String location)
public List<Beer> searchFor(String criteria)
{
+ searchBox.clear();
searchBox.sendKeys(criteria);
searchBox.sendKeys(Keys.ENTER);
- waitUntilTableContentChanged();
+ if (errorDisplayed())
+ {
+ return Collections.emptyList();
+ }
+ else
+ {
+ waitUntilTableContentChanged();
+ }
return transformRowsToBeers();
}
@@ -64,8 +79,19 @@ public Beer detailsOf(String criteria)
return openDetailsForFirstMatchingBeer(criteria);
}
+ public void errorMessageShouldBeDisplayed(String errorMessage)
+ {
+ WebElement errorMessageTextField = getErrorMessageTextField();
+ assertThat(errorMessageTextField.getText()).isEqualTo(errorMessage);
+ }
+
// --- Private methods
+ private WebElement getErrorMessageTextField()
+ {
+ return driver.findElement(By.id("advisor:error"));
+ }
+
private Beer openDetailsForFirstMatchingBeer(String criteria)
{
linkToFirstMatchingBeer(criteria).click();
@@ -93,14 +119,14 @@ private WebElement linkToFirstMatchingBeer(String criteria)
*/
private void waitUntilTableContentChanged()
{
- final List<WebElement> tableRows = driver.findElements(By.xpath(RESULT_TABLE_XPATH));
+ final Set<WebElement> originalTableRows = Sets.newHashSet(driver.findElements(By.xpath(RESULT_TABLE_XPATH)));
final ExpectedCondition<Boolean> rowsInTableChangedCondition = new ExpectedCondition<Boolean>()
{
@Override
public Boolean apply(WebDriver input)
{
final List<WebElement> currentTableRows = input.findElements(By.xpath(RESULT_TABLE_XPATH));
- boolean domTableContentChanged = !Sets.newHashSet(tableRows).contains(Sets.newHashSet(currentTableRows));
+ boolean domTableContentChanged = !originalTableRows.contains(Sets.newHashSet(currentTableRows));
return domTableContentChanged;
}
};
@@ -109,4 +135,22 @@ public Boolean apply(WebDriver input)
wait.until(rowsInTableChangedCondition);
}
+ private boolean errorDisplayed()
+ {
+ try
+ {
+ final WebDriverWait wait = new WebDriverWait(driver, SECONDS_TO_WAIT, POLL_EVERY_MS);
+ wait.until(ExpectedConditions.presenceOfElementLocated(By.id("advisor:error")));
+ return true;
+ }
+ catch (NoSuchElementException e)
+ {
+ return false;
+ }
+ catch (TimeoutException e)
+ {
+ return false;
+ }
+ }
+
}

0 comments on commit 809682e

Please sign in to comment.